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

Back in our last post (Part I - Each), we created a function called each. Here it is again:

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);
  }
}

Remember, we decided to only deal with handling arrays in our implementation of each -- normally, it also handles objects.

We used it with two different functions, count and print:

function count(string) {  
  return string.length;
}
function print(string) {  
  console.log(string);
}

Let's try Map

Map is slightly different from each, but its implementation is really similar.

Just like each, map also takes in two parameters: An array and a callback function.

But unlike each, map actually returns something: An array with elements manipulated by that callback.

Remember the pets array we had earlier?

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

Let's say that we want to return an array with the lengths of each pet's name:

map(pets, count) // returns [3, 3, 6, 7, 6]

But how do we build this?

Well, we know that we have to return some sort of array, and that the array is populated with the results of whatever our callback returns:

function map(arr, otherFunction) {  
  // Create an array to store our values
  var result = [];
  // Iterate over the input arr
  for (var i = 0; i < arr.length; i++) {
    // Within each iteration, we want to call otherFunction and pass in our element
    // We also want to push the results of that call over to our result array
    result.push(otherFunction(arr[i]));
  }
  // At the end, we want to return the actual array
  return result;
}

That's great, but we can take this one step further. Remember how each basically does all of the iteration for us? Well, we can integrate each within map quite easily:

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;
}

Great! What we've just done is a very important principle of programming: Keeping things DRY.

DRY stands for Don't Repeat Yourself. If you find yourself writing the same code over and over again (in our case, the for loop and how it handles a callback), there's usually a way to modularize it, write it once, and use it in many places.

In our example above, we used each within map to perform our iteration, resulting in us using an anonymous function as the callback for each to handle pushing our results of the callback passed to map into our results array.

Hope you stick around as we jump into filter next time.