Note: This is a mult-part series! You're going to benefit the most following it from the very beginning, since we re-use code and concepts from previous posts to build our newer ones.

Back to Basics: Functional Programming

We're going to look at something a little bit different now. Filter brings in the complexity of boolean values (true or false).

Remember our pets array and our map function?

var pets = ['dog', 'cat', 'parrot', 'hamster', 'lizard']

function map(arr, otherFunction) {  
  // Create an array to store our values
  var result = [];

  // Call `each`, which iterates over our values and fires a callback:
  each(arr, function(elem) {
    // We're using an anonymous function here to handle the pushing of results. We're still calling otherFunction, passing in the element being iterated over.
    result.push(otherFunction(elem));
  })
  // At the end, we want to return the actual array
  return result;
}

And each, in case you forgot what it does (remember, again, we're only going to address arrays in our implementation of each):

function each(arr, otherFunction) {  
  // Iterate over the input array
  for (var i = 0; i < arr.length; i++) {
    // Call otherFunction at each iteration, passing in the current element, i, and the entire array in case otherFunction needs them
    otherFunction(arr[i], i, arr);
  }
}

The way filter works is that it, like map before it, accepts an array and callback. Also similar to map is the fact that filter returns an array of values.

Here's the twist: filter only adds values to that array it returns if it passes a truth test. That truth test, in turn, is determined by the callback.

Let's say our truth test involves the number of letters in a pet's name, and we want to filter only pets with five or more letters in their name.

function filter(arr, otherFunction) {  
  // Create an array to store our values
  var result = [];

  // Call `each`, which iterates over our values and fires a callback:
  each(arr, function(elem) {
    // If otherFunction returns true after being passed in the current element,
    if (otherFunction(elem)) {
      // Push the current element to our results array.
      result.push(elem);
    }
    // No else condition, we just ignore it and move to the next iteration if it returns false.
  })
  // Return our results array at the end.
  return result;
}

Great. A callback to check for length five or greater could look like this:

function fiveOrGreater(string) {  
  // If this statement evaluates true, we return true. Otherwise, it returns false
  return count(string) >= 5;
}

Note how we also re-use count within this function, so we don't have to rewrite it. Count is, from before:

function count(string) {  
  return string.length;
}

Now when we run:

filter(pets, fiveOrGreater) // returns ['parrot', 'hamster', 'lizard']

But there's more optimzations we can work with.

For one, we don't have to create fiveOrGreater as a function of its own if we only plan on using it once. Just like with each, we can write it as an anonymous function:

filter(pets, function(elem) {  
  return count(elem) >= 5;
}) // still returns ['parrot', 'hamster', 'lizard']

But wait, couldn't we keep this even more DRY by utilizing map within filter? Well, the thing is, map indiscriminately pushes everything to our return array so we wouldn't be able to successfully do this.

We're about to dive into the world of reduce in the next post. Hope you stick around.