What is functional programming?
Functional programming (FP) is all about the idea of functions as a mapping from one value to another. An FP function just turns one value into another – it doesn’t have side effects. Side effects are anything that happens within the function that changes something outside of the function. For example, changing the value of a variable not defined in the function, or logging output, or showing an alert message … basically anything that happens in the function. The only thing an FP function does is takes in a value, and returns a new value.
Another interesting thing about FP is the use of higher-order functions. These are functions that either take or return functions as values (or both). I’m mainly going to be looking at functions that take other functions as parameters, because there are some interesting things you can do with that.
select etc. I’ll walk through some of these to demonstrate the power of FP. Note that functional programming isn’t just about working with collections – there are lots of other exciting things you can do – but for now I’ll concentrate on the collections.
Mapping over an array
One of the most widely used Underscore functions is
_.map. This takes an array and a transforming function, and creates a new array based on the return value of the transforming function. That’s a bit abstract so I’ll give you an example:
_.map is passed an array, and a function. That function is called on each element of the array in turn, and the return value of the function gives the corresponding element in the new array. Note that the original array is left intact. The
_.map function takes an array, and returns another array – it’s a mapping from one value to another.
You can do much more interesting things with
_.map than just multiplying numbers though. You could transform an array of strings into an array of cats!
I hope you’ll forgive me for using two Underscore functions there. First off, we’ve got
_.map. In this case, we’re going through the array of cat names, and creating an array of cats. The second is
_.each. This, like
_.map, goes through each element of the array, passing them into the function, but it doesn’t care about the return value. It just executes the function and carries on with its life. Now, if you’re concentrating, you may have noticed that
each isn’t actually a mapping from one value to another, and you’d be right.
_.each is only useful if you allow side effects, for example
What’s great about
_.map is that once you’ve learned to read it, and understand what it does, it really succinctly explains the meaning of your code. In that cat example, you can see that all the
In comparison, isn’t that just damn ugly? I mean, to read that you need to keep track of the array, and the array index, and the length of the array, and you have to make a new blank array to contain the new cats, and … you get the point. It’s mixing up the how with the what. All I care about is that I’m getting an array of cats, from an array of cat names. Don’t bother me with insignificant details like array indices.
Here’s another example: constructing a query string:
This one uses an object, but the same principles apply. From a list of key/value pairs, we’re constructing an array of ‘key=value’ strings. Then all you need to do is
join the array with
&s. This describes how a query string is formed much more declaratively than the standard
append the key, then an equals, then the value, then an ampersand, then the next key, then the next value, then another ampersand, then – oooh we’re at the end – better get rid of that last ampersand, whoops!
Go forth and map-ify!
for loops and embrace the
_.map. If all you’re after is
each, and you’re using jQuery, you’ll be glad to know both functions have jQuery equivalents: jQuery.map and jQuery.each, albeit with a slightly different API. Next time I’ll be looking at some of Underscore’s other functions, for the times when
_.map just won’t cut it.