Save 37% off The Transparent Web with code fccwilson at manning.com.

The definition of functional programming that I’m going to offer is pithy. Functional programming is about programming using mathematical functions. Before you run screaming into the mountains, take a second to recall some terminology. In mathematics, a function relates an input to an output. We call the input the domain of the function and we call the output the range. In programming, we stick with the terms input and output, but it’s helpful to know both.

More abstractly, you can think of functions as a way of matching-up two collections of things. Imagine two fuzzy clouds full of things floating free in our mathy dreamscape. Got that? Let’s say the first cloud consists of some shapes: a square, a circle, and a triangle. In the second cloud there’s a smiley face, a plus sign, and a square. Now draw arrows between a thing in the first cloud to a thing in the second cloud. Each arrow starts on an item from the first cloud and ends on an object in the second cloud; you’re thinking about a function. Here’s what that looks like.

Figure 6.1. A function mapping elements in the domain to elements in the range

Numerous picky points exist that you should be aware of when talking about a mathematical function. Most of these I won’t talk about because this article would quickly turn into a book! If you’re interested, go check out Khan Academy, which has a good intro to mathematical functions. The key thing to know about functions in functional programming is that every input uniquely determines an output. Visualizing that in the picture above, two different arrows are allowed to point to the same element, but only one arrow may leave an element. Let’s look at an example in code. Imagine we have a function which converts a number into English. If I run humanize(5) the function should return five.

We’d then describe the parts of that function like this:

// Type could also be written:
// int -> string

humanize(num: int) : string { ... }
^^^ ^^^^^^
domain range
|     |
|     _----- "set of all strings"
|
_----------------"set of all integers"

Passing in the same number always yields the same string as output, and every input uniquely determines an output. Yay! It’s a function.

What it means to be functional, a little more formally

You may sometimes hear functional programming defined in this way: in functional programming the return value of a function only depends on its input. We can make that statement more precise. Let’s say we’ve a function f and an argument x. Furthermore, let’s say that f applied to x returns y:

f(x) = y [1]

Which means, whenever you see an f(x) you may substitute in a y and vice versa. This is what the equals sign means. And let’s also say that we have this specimen:

f(x) = z [2]

We can substitute the f(x) in equation 2 with y:

y = z

And we’ve shown that y = z.

Or written another way:

f(x) = y && f(x) = z => y = z

Given the same input, there’s no way to get two different outputs.

The extent to which various languages and platforms follow this idea vary greatly. It’s helpful to have the mathematical understanding in mind when looking at functional programming languages. But it’s also useful to have languages where almost all the functions are mathematical functions. You still get a whole lot of benefit, but the terminology isn’t as cooperative. In most of the material you’ll see online or in programming books, the non-mathematical meaning of function is more prevalent. To avoid confusion, the term purely functional is used when we’re talking about programming functions that behave like mathematical functions.

How Functional Programming Helps

Initially, it can seem that functional programming introduces a host of new concepts, and it does. But the beauty of the ideas of functional programming is that they collapse many different concepts into broader, simpler, and more generally applicable ones. Purity, immutability, everything-is-a-value, and many more aspects common to functional programming flow out of simple underlying ideas. When we understand how those work and the style of programming that they imply, we get to chuck a lot of accidental complexity.

The term accidental complexity comes from an essay entitled No Silver Bullet by Fred Brooks. It could be paraphrased as difficulties encountered when solving a problem that don’t arise from the problem itself, but from what we do trying to solve the problem. When we work at a fine level of detail, we tend to invite even more detail. If we want to increment a variable once per loop, do we do it at the start of the loop or the end? And do we want increment-then-return i or do we want return-then-increment i? There are a host of these details that we could get wrong – and we usually choose to add even more details as we go, adding more places for things to go south.

The inherent mental tax of having to maintain an understanding of all these details adds complexity. It’s as if we had to understand it’s three o’clock, by thinking about the positions of all the individual gears in our watch. Effective problem solving is as much about identifying what to ignore and simplify, as it’s about what to pay attention to. Having lots of detail and extraneous information is begging for trouble. The big insight that accidental complexity gets at is that it matters how we solve a problem. We can make it harder than it needs to be, but we don’t have to.

Functional programming is a style that emphasizes what to do and not the individual steps of how. We can sidestep some of the details and trim some of that accidental complexity. Let’s look at two short code snippets showing the difference between how & what.

The first way will be more how-ish and the second will be more what-ish. Think of this like a toy which says some assembly required versus taking a toy out of the box.

Imagine we’ve an array full of JavaScript objects which represent users. We’ll make  the simplest JavaScript object we can, by representing a user like this: { uid: 1, active: true }. To put this in an imaginary context, think of a web page with a button marked Deactivate all users. We want the values of all the active keys set to false. We’re tasked with writing code to make that happen.

Our first take is to use a programming language feature that I assume everyone is familiar with, a loop. Here’s how we’d manage that change using a loop:

Listing 6.1. A loop: how to do (something)

function deactivateUsersLoop(users) {
for (var i = 0; i < users.length; i++) {
var user = users[i];
user.active = false;
}
}

Inside the loop we access the current user.

We then modify the active property in-place to be false. This mutates the item, and hence the list, that was passed into deactivateUsersLoop.

Loops are orchestrate each step. We go through the array of users one by one, and do something to each. We have to spell out exactly how we’re going to step through them. This means counting how many elements there are and using an index to look at each one, as if we were an assembly line. Once we’ve incremented our index past the end of the array, it’s time to stop.

I’ve written code like this a zillion times. It took me a long time to realize that this approach is fishy. The array index is disconnected from the underlying array, it’s an independent counter that the for loop weakly manages for us. It also seems distant from the gist of what I want to do. I wouldn’t describe code like this in the way that I write it. I’d say something more like: deactivate all the users in this array. Notice how I immediately went up a level to talk about all the users?

Functional programming encourages wholemeal programming, or attacking a problem all at once. What if we could handle the whole array at once and express our desire to do something to every element? Enter the map function, which lets us say exactly that!

Listing 6.2. A mapping: what to do

function deactivateUsersMap(users) {
var deactivate = function(user) {
return { uid: user.uid, active: false };
}
return users.map(deactivate);
}

First off, we define an inner, private function called deactivate.

This function returns a new user, which is created with its active property set to false.

We apply this function to each element of the users’ array, returning a new one in the process. Notice

that we created an entirely new array in the process. This differs from the looping version.

We’re able to express the solution in two simpler parts.

• What we do with a single element.
• Use map to apply that solution to each element in the array.

Being able to solve smaller problems is common with functional approaches. Often, FP enables us to first decompose the problem into possibly more, but simpler parts. Once the problem has been sliced and diced, then you’re able to recombine them to get to a solution.

Using a function in FP

I said earlier that the shift to FP causes lots of other things to flow out from that move. One thing that may not be immediately obvious is that the way that you use functions must change. Function return values become the sole channel through which information can flow. A function is a black box where we only know what we passed into it and what it returns. Functional programming, by getting rid of mutability, eliminates other channels of information.

Without any other way to communicate back to the outside world from within a function, the return value becomes the sole result of running the function. As with a black box, we can completely ignore the details of how a function operates, and the result. In contrast, languages like C will often call a function and not directly use the value!

The return value is merely for signaling an error, and the real return value is accomplished by modifying one of the inputs. A good example of this is inet_aton in the C standard library. It takes a string representing a dotted IP address and an empty structure for holding the result (a native IP address representation) and then modifies the second argument to contain the answer. The return value, an int, indicates whether or not the function ran successfully.

You can see the difference between the approaches below:

var inactiveUsers = deactivateUsersMap(users);
deactivateUsersLoop(users);

Because deactivateUsersMap is written in a functional style, we must use the return value, otherwise calling the function has no effect! But with the looping version, deactivateUsersLoop, we can ignore the return value . This is a huge and telling difference between the functional and the imperative or object oriented approaches.