Sunday, February 1, 2015

Reducing Filter to Reduce OR All You Need is Fold

"All springs reduce their currents to mine eyes"
-- Shakespeare, Richard III
Act II, Scene II, Line 68

Intro


Last time we look at using the ideas presented in Graham Hutton's paper "A tutorial on the universality and expressiveness of fold" around mapping map to a fold.  This post will look at filtering filter down to a fold.

Filter


Filter goes by many different names, to those who speak Clojure, Haskell, and Underscore.js it is called Filter, to others that speak C# it is know as Where, while those that speak C++ know it as Remove, ... we could go on like this for a bit.



The point is that this is the same idea called by different names.  With a Filter what you are doing is taking a collection and applying a predict which state which members of the collection to let into the resulting collection and which members to not allow.  Think of it as a bouncer at a club, some of the people looking to get in will be admitted to the club others will be turned away, the bouncer is the predict, the people are the collection, and those few that get into the club are the resulting collection.

An easy example is to filter out all members of a collection of integers which are not odd.  In Clojure and C# we could use the following code to do this.



We see in both languages that we can use a higher order function to filter our collection down to the resulting collection with the property of oddness that we are looking for.  Clojure has a built in predicate function to check for oddness of a number while in C# we have to roll our own with a lambda function.

Fold


We talk about Fold last time, but we'll review it really quick.


When we are talking about Fold we are talking about taking a collection and applying a function against each member of the collection resulting in a result of a single "value".

Hmm, this sounds kind of similar to what we are doing with Filter...

Folding Filter into a Fold


When we looked at Filter we saw some similarities to Fold.

  1. apply a function to each member of a collection
  2. building a result

In fact we could look at Filter in the following way:


If we take a Fold (aka Reduce), a predicate function, and a collection to hold the resulting collection, we end up with a Filter.  We can looking at the following examples in Clojure and C# using our friend isOdd with a Fold to produce a Filter



In the Clojure code we see that we have a predicate function testing if a value is odd and if it is we conj it to a memorized resulting collection else we just pass along the memorized result collection.  We seed the Reduce (aka Fold) with an empty vector was is used to hold the memorized result collection.  Note, the memorized result collection is %1 in the lambda function while the current member we are looking at is %2, this pattern is typical in Folds across different languages (I cannot think of one which does not have this as the order, but maybe one exist).

In the C# code we new up a List to hold our resulting collection and in our lambda we test the current member we are looking at, if it passes we add it to the memorized result collection, then we always pass the memorized result collection along to the next call of Aggregate (aka Fold).  Since we had an array of integers as our input, we need to reshape the result collection with a call to ToArray.

By looking at this simple example we see that all we really need is Fold.  :)