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
- Part I - with Each
- Part II - with Map (you're here!)
- Part III - with Filter
- Part IV - with Reduce
- Part V - with MapReduce
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.