Latest blog post:

permalink

Functional Programming in JavaScript

Introduction

Most people start using JavaScript as simply a means to an end. You need to use it in order to accomplish anything of significance on a web page, unless all you want to do is render static content. Adopting this perspective at first makes it really difficult to see the fun and interesting parts of JS that aren't related to its habitat in the browser. The property that interested me the most was its ability to adopt the role of a functional programming language. In this post I'm gonna dive into what this means, and why JavaScript is a great platform for implementing and learning about functional programming.

What is it?

Functional programming is part of a programming paradigm called Declarative programming, which is the compliment to Imperative programming. The simplified difference between functional and imperative programming is that a function in the former will produce a result that yields no side effects. This basically means that functional programs are stateless, and depend only on input parameters. In the context of programming languages, this means that there are no lasting variable assignments made during a function's execution that will affect future executions. Imperative programming does not require this, and may be as stateful or procedural as is needed. Under these definitions, we can think of functions in FPLs as being "black boxes" in the mathematical sense, while functions in IPLs may share more similarities with finite state machines.

To provide a good overview of the features of functional programming that we can find in JS, I'm gonna do a quick run through of some of the important aspects of FP, and point out how they can be applied in JavaScript.

Here we go!

First class functions

This is the first thing about JavaScript that screams "functional" to me. First class functions are basically functions that can be treated like any other data object (such as a number or a string). They are "first class" in that they have the freedom to do whatever they want. We can create such a function in JS like so:

let triple = function(number) {
    return number * 3;
}

triple is now a variable that we have full control over. It's first class in that we can pass it around, re-assign its value, and use it as a parameter to other functions. An example of this would be the following:

let data = [1, 2, 3];
data = data.map(triple);
console.log(data);   // [3, 6, 9]

This is a very good segway into the next functional concept that JS takes advantage of. Array.map is what is known as a higher-order function. This is any function that can take another function as a parameter, or return a function as a result. Using higher-order functions is a great way of making use of functions as first-class citizens. Let's make another function in the same vein as triple, but instead of returning the tripled value, it will return a function that will multiply inputs by a value that we specify. If this is unclear it will be cleared up by the code:

function getMultiplyFunction(multiplyBy) {
    return function(num) {
        return num * multiplyBy;
    }
}

let triple = getMultiplyFunction(3);
let quadruple = getMultiplyFunction(4);

console.log(triple(100));     // 300
console.log(quadruple(100));  // 400

Now we have a general function that will return any multiply function we can conceive of! Heck yeah.

Array.map is an example of another kind of higher-order function, since it takes functions as input rather than returning them. Other examples of this (that also operate on arrays) are the filter and reduce functions. This is the first video in an excellent series that covers these functions, and also functional programming as a whole. I highly recommend this channel in general, especially for anyone interested in JavaScript.

Recursion

Now let's take the implications of functional programming laws and apply them to a very common case: loops. By the definition of a functional program, it can't implement loops in the way we might normally try to. Since no values can be assigned, we can't keep track of state and by extension we can't keep track of when we should stop looping. That's a pretty big roadblock to be faced with, since our good friends while and for are now certainly off the table as they both must keep track of some state-keeping variable to determine when to terminate. Luckily, there is a way to perform the same operations that still obeys FP: Recursion.

We aren't saying anything too special about JavaScript when we point out that we can perform recursion with it. Any programming language worth it's salt will allow you to throw a recursive call of a function into itself. As such, the purpose of this section is mostly to discuss recursion in the context of FP. Despite this, let's look at an example of recursion in JavaScript and see how it all comes together.

The following function computes the sum of all the values in an array recursively

function sum(numbers) {
    if (numbers.length == 1)
        return numbers[0]
    else
        return numbers.pop() + sum(numbers)
}

sum([1, 2, 3])      // 6

As you can see, this function doesn't make use of variable assignments to determine when to terminate. The recursive call (the else block in this case) allows the function to build a stack of values to compute, that depend on the call one level up. Once the base case is reached, we've provided a concrete value that the function can confidently return, and all of these dependencies are resolved.

So we've shown that JavaScript holds up in the recursion department as well.

Conclusion

What's great about all of this is that JavaScript is only a functional language when we want it to be. We have the freedom to make our JavaScript as beautifully and pretentiously functional as we want, or implement things in a 100% object oriented manner, or simply write a procedural script. The freedom offered by JS are what make it fun as hell and also incredibly ugly at times. It puts the job on the programmer to hold themselves to the programming paradigms that they believe are going to benefit the software that they're writing, where other languages like Java or C++ impose structure far more strictly. Knowing this, it's good to keep functional programming in mind as just another way that we can leverage JS to do exactly what we want.

Here are some others: