A Gentle Introduction to Functional JavaScript: Part 3

Written by James Sinclair
on the 6th February 2016

This is part three of a four-part series introducing ‘functional’ programming in JavaScript. In the last article we saw how we can use functional programming with arrays and lists. In this article we examine higher-order functions—functions for making functions.

Functions for making functions

At the end of the last article, I said that going further down the functional path is not for everyone. That is because once you get past list-processing functions, things start to get a little weird. What I mean is that we started with abstracting collections of instructions into functions. Then, we abstracted for-loops into map and reduce. The next level of abstraction is to start refactoring patterns of creating functions. We start using functions to make other functions. This can be powerful and elegant, but it starts to look a lot less like the JavaScript you might be used to writing.

More building blocks

Functions for making other functions are sometimes called higher order functions. To understand them though, we need to revisit some of the built-in language features of JavaScript that make higher order functions possible.

Closures and Scope

One of the more difficult things to wrap one’s head around in JavaScript which variables a function can ‘see’. In JavaScript, if you define a variable inside a function, it can’t be seen outside the function. For example:

This takes a bit of getting used to. The rules are fairly straight-forward, but once we start passing variables around as arguments, it becomes harder to keep track of which functions can see which variables. If it’s confusing at first, be patient: Look at the point where you defined the function, and work out which variables are ‘visible’ at that point. They may not be what you expect if you are just looking at the point where you’re calling the function.

The special arguments variable

When you create a function in JavaScript, it creates a special variable called arguments, that is sort of like an array. It contains the arguments that are passed to the function. for example:

Notice that the output is more like an object with keys that happen to be integers, rather than an actual array.

The interesting thing about arguments is that it contains all the arguments passed in a function call, regardless of how many are defined. So, if you call a function and pass it extra arguments, they will be available in the arguments variable.

It is often useful to have the arguments variable as an actual array. In those cases we can convert the arguments variable into a real array by using a built-in array method called slice. Because arguments isn’t is a real array, we have to do it by a roundabout route:

One of the built-in methods for functions is call and it allows you to call a function another way:

twinkleTwinkle.call(null, 'star');
//=> Twinkle, twinkle, little star

The first argument to the .call method defines what the special variable this refers to inside the function. But we can ignore it for now. Any arguments after this one are passed directly to the function.

The .apply method is much like .call, except that instead of passing individual arguments one-by-one, .apply allows you to pass an array of arguments as the second parameter. For example:

Both of these methods will be useful when we are building functions that create other functions.

Anonymous Functions

JavaScript allows us to create functions on the fly. Wherever we might create a variable, then do something with that variable, JavaScript will let us stick a function definition right in there. This is often used with map and reduce, for example:

We’d like to use this with map to add a class to a bunch of elements, but we have a problem: the map passes array items one by one as the first parameter to the callback function. So how do we tell addClass which class name to add?

The solution is to create a new function that calls addClass with the class name we want:

This works great when we know our function takes exactly two parameters. But what if we want to partially apply with a function that takes three parameters? Or four? And what if we wanted to partially apply more than one variable?
For these cases we need a more generalised partial application function. We’ll make use of the slice and apply methods described above:

JavaScript has a built-in method that sort-of works like partial called bind. It’s available as a method on all functions. The trouble is that it expects its first parameter to be an object you want to bind the special this variable to. This means, for example, that if you want to partially apply something to document.getElementById, you have to pass document as the first parameter, like so:

Composition

We said in the last article that functional programming is about taking small, simple functions and piecing them together to do more complex things. Partial application, as we saw above, is a tool that makes that process easier. With partial application we can convert our addClass function and convert it into a function we can use with map. Composition is another tool for combining simple functions together.

The simplest form of composition is with two functions, a and b, both of which expect just one parameter. Compose creates a third function, c. Calling c with a parameter x returns the result of calling a with the result of calling b with x… What a confusing mess. It’s much easier to understand by looking at an example:

Now, this is pretty good. We can get a long way with just composeTwo. But, if you start to write ‘pure’ functions (we’ll discuss this later), then you may find yourself wanting to join more than two functions together. For that we’ll need a more generalised compose function:1

The real power of compose becomes clearer once we combine it with the curry function. But even without currying we can begin to see that if we have a collection small utility functions handy, we can use compose to make our code clearer and more concise. For example, imagine we have a plain-text poem:

Now, that poem won’t display so well in a browser, so let’s add in some line breaks. And, while we’re at it, let’s translate brillig into something easier to understand. And then we’ll wrap the whole thing in a paragraph tag and a block quote. We’ll start by creating two very simple functions, and build everything else from there:

Notice that if you read the arguments to compose from left to right, they are in reverse to the order they are applied. This is because compose reflects the order they’d be in if you wrote them out as nested function calls. Some people find this a little confusing, so most helper libraries provide a reversed form called pipe or flow.

Using a pipe function, we could write our modifyPoem function as follows:

Currying

A limitation of compose is that it expects all the functions passed in to take just one parameter. Now, this isn’t such a big deal now that we have a partial function—we can convert our multi-parameter functions to single-parameter functions with relative ease. But it’s still a little bit tedious. Currying is kind of like partial application on steroids.

The details of the curry function are a little complicated, so first, let’s look at an example. We have a function formatName that put’s a person’s nickname in quotes. It takes three parameters. When we call the curried version of formatName with less than three parameters, it returns a new function with the given parameters partially applied:

This is all very convenient, but it doesn’t give us all that much over partial. But what if, just suppose, we happened to curry every function we make, just by default. Then, we could create almost any function by combining other functions with composition (and currying).

Remember our poem example from earlier? What if we wanted to wrap emphasis tags around ‘four o’clock in the afternoon’ string we replaced?

But why?

So far, we’ve looked as partial, compose, pipe, and curry as useful tools to piece together small, simple functions to create more complex ones. But, are they really that useful? What do they make possible that wasn’t possible before? Well, what it does is open up a whole new style of programming. It lets us think about problems in different ways, which makes certain classes of problem become much easier to solve. It can also help us write more robust, verifiable code. This will be the topic of the next article, so if you’re curious, read on…

This particular version of compose is based on the implementation used by Underscore.js. ↩