Javascript Functional Programming

Categories: software development | Technology |

In the previous blog post “Why you should consider Functional Programming“, we discussed the benefits of changing our mindset into a more interesting approach.

The advantages of functional programming include:

  • Elegance and simplicity
  • Easier decomposition of problems
  • Code more closely tied to the problem domain

And through these, we can also achieve:

  • Straightforward unit testing
  • Easier debugging
  • Simple concurrency

In today’s blog post I want to explore with you the perks of coding in a functional way with Javascript.

Javascript Functional Programming

Why JavaScript?

Before getting our hands dirty on the code, there are a few things we should consider. There are languages expressly created to work under a functional programming style like Haskell, Scala or Lisp. Unfortunately, the number of developers who are familiar with these technologies is rather limited. Moreover, those languages don’t run in the browsers installed in all our devices.

By acknowledging that JavaScript is becoming ubiquitous, and is one of the most popular programming languages being used, we can focus on its characteristics that allow us to consider it for the functional programming paradigm.

Functional programming is a natural fit for JavaScript, because it offers a few important features:

  • First-class functions
  • Closures
  • Simple lambda syntax

Let’s examine each of these in turn.

First-class functions

JavaScript makes it easy to assign functions to variables, pass them into other functions, return functions from other functions, compose functions, and so on. JavaScript also offers immutable values for primitive types, and features that make it easy to return new objects and arrays rather than manipulate properties of those that are passed in as arguments.

Why is all that important?

Functional programming glossaries contain a large number of large words, but at its core, the essence of functional programming is really very simple; programs are built mostly with a handful of very small, very reusable, very predictable pure functions.

There are some tools built in to modern JavaScript environments, and it’s straightforward to roll your own. Some of these features are readily available in JavaScript. Others can be used if care is taken. And some are essentially impossible at the language level.

Note: ES6 will include most of the missing features traditionally included in declarative languages.

Closures

Like objects, closures are a mechanism for containing state. In JavaScript, a closure is created whenever a function accesses a variable defined outside the immediate function scope. It’s easy to create closures: simply define a function inside another function, and expose the inner function, either by returning it, or passing it into another function.

1
2
3
4
5
6
7
8
9
function sayHello (name) { 
    var text = "Hello " + name, // Local variable 
        say = function() { console.log(text); } 
 
    return say; 
} 
 
var greet = sayHello("Bob"); 
greet(); // logs "Hello Bob"

The variables used by the inner function will be available to it, even after the outer function has finished running.

Lambda calculus

For those who haven’t heard before about Lambda Calculus, the name itself can be daunting. But don’t let that fool you: it’s actually very easy. Lambda is just a mapping relationship between x and y. The reason it is named as lambda expression is that these functions are always used once or a few times, which do not need a function name. Take into account that Lambda is a mapping from only a single parameter.

Let’s say we want to create a function that multiplies x by y. Remember: lambda maps only from one single parameter. So, conceptually we can think of it like this:

1
(x) -> (y -> x*y)

The first lambda function returns another lambda (y -> x*y) which also accepts a single parameter.

For example, we pass the number 5 to the first lambda

1
(5) -> (y -> 5*y)

We can now see that we get another lambda function that maps y to y*5. If we pass the number 4 into this new lambda, we get:

1
4 -> 5*4

We can say that the function (x,y)->x*y is the combination of two lambdas, instead of one lambda as it looks like. Where did we see that before? That’s right, Javascript anonymous functions!

1
2
3
4
5
6
7
function multiply(x){
    return function(y){
        return x*y;
    }
}
 
multiply(2)(3) // => 6

Anonymous functions can be passed as parameters and returned as values in JavaScript. That type of function are called high-order functions. And that’s the underlying concept of using JavaScript in a functional programming paradigm.

Most common functional programming functions in Javascript

map

One of the most fundamental functions used in functional programming is map, which is used to convert one list into a related one by running the same function against each member.

Say that we are given an array of numbers and we want to return a new array with the squares of those numbers, ordered in the same way. Let’s see the imperative approach, where we describe how to do it:

1
2
3
4
5
6
var numbers = [1, 2, 3, 4, 5];
 
function convertToSquares(array) {
    var squaresArray = [];
 
    for (var i = 0, len = array.length; i < len; i++) { squaresArray[i] = array[i] * array[i]; } return squaresArray; } convertToSquares(numbers); // => [1, 4, 9, 16, 25];

Now let’s try to do it with the map function. The map function will apply a transformation of each of the elements in the array and return a new transformed array. This is exactly the use for lambda functions:

1
var fiveSquares = map(Math.sqrt, [1, 2, 3, 4, 5]); // => [1, 4, 9, 16, 25];

Note: this isn’t traditional JavaScript syntax. It’s been rearranged in the way the library Ramda does it for the sake of simplicity.

Math.sqrt is the transformation lambda function applied to every element of the array. See the difference? It’s definitely shorter and when we read it, it’s easier to understand because we’re focusing on what needs to be done, rather than how to do it. We delegate that task to the mapping function.

reduce

Another very important function used in functional programming is reduce, which is used to convert one list of values into a single value. For example, let’s say that we want to add up all the numbers in an array. With the imperative approach we would do something like:

1
2
3
4
5
6
var numbers = [1, 2, 3, 4, 5];
 
function addArray(array) {
    var result = 0;
 
    for (var i = 0, len = array.length; i < len; i++) { result = result + array[i]; } return result; } addArray(numbers); // => 6

Now we’ll try to do it in the functional programming way. The reduce function will transform the array by using an anonymous function (lambda function) that gets the previous value, the one returned by the last invocation of the function, and the current value that is being processed. The partial outcomes will be stored in an accumulator that, in the last call, will have the final value.

1
2
3
4
5
6
var numbers = [1, 2, 3, 4, 5];
 
var total = numbers.reduce(function(a, b) {
  return a + b;
});
// total => 15

The accumulator will be defaulted to 0 if we don’t pass a value.

Even better would be for us to be able to reuse that adding function. So, we could do:

1
2
3
4
5
6
7
8
var numbers = [1, 2, 3, 4, 5];
 
function add(a, b) {
    return a + b;
}
 
var total = numbers.reduce(add);
// total => 15

filter

As the name suggests, filtering is a process where we extract values that meet certain criteria from a list. It’s easy to see it from an example. Let’s assume that we have a list of objects that represent people by different dimensions:

1
2
3
4
5
6
7
8
9
{
    name: "John",
    dob: "11/25/1983",
    city: "St. Louis",
    state: "MO",
    height: "6' 3''",
    weight: 210,
    sex: "M"
}

What we want to do is create a new list from the original list of people where its only members are men that weigh under 200lbs

The imperative style approach:

1
2
3
4
5
6
7
8
9
10
11
12
13
var people = [{...}, {...}, ...];
 
function extractPeople(array) {
    var newPeople = [];
 
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].sex === "M" && array[i].weight < 200) {
            newPeople.push(array[i]);
        }
    }
 
    return newPeople;
}

But that is not descriptive as we are stating how to do it. Let’s see the functional style:

1
2
3
4
5
6
7
var people = [{...}, {...}, ...];
 
function criteria(person) {
    return person.sex === "M" && person.weight < 200;
}
 
var newPeople = people.filter(criteria);

We’ve done something important here: We’ve moved the focus from iteration and updating the state of a local collection to the real point of this block — choosing the people with the proper properties values.

One of the most important features of functional programming is that it makes it easy to shift focus in this manner.

Note: that criteria function can be improved using a points-free or tacit programming approach, which we won’t see here.

compose

Composing two functions means that we first apply one of them, and to the outcome of that, we apply the other function. Graphically (g.f)(x) is equivalent to g(f(x)), which is a function composed from f and g. A very simple implementation can be coded like this:

1
2
3
4
5
var compose = function(f, g) {
    return function(x) {
        return f(g(x));
    };
};

Let’s say someone asks us to sum all the numbers in an array and then apply the square root to the result. How can we do that with functional programming using what we’ve built so far?

1
2
3
4
5
6
7
8
var numbers = [1, 2, 3, 4, 5];
var reduce = Array.prototype.reduce; 
// So we can use it with call()
 
var reduceAdd = function (a) { return reduce.call(a, add) };
 
var total = compose(Math.sqrt, reduceAdd)(numbers); 
// => 3.872983346207417

curry

The last function we’ll see in this post is probably the most foreign to the imperative programming style. Currying (others call it partial application) is the process of converting functions that take multiple arguments into ones that, when supplied fewer arguments, return new functions that accept the remaining ones.

Using closures we can code a function that is a factory for a sum function. That is, accepting just one argument it will return a function that sums any number to that argument:

1
2
3
4
5
6
7
8
var add = function(a) {
    return function(b) {
        returns a + b;
    }
};
 
var add42 = add(42);
add42(7); // => 49

In this example, the add function can be used in just one way: by passing it a single parameter, storing the returned function in a variable and calling it afterwards by passing a different parameter.

Wouldn’t it be great for our add function to support both flavors? I mean, if we pass two parameters, the function would just return the result but if we pass a single parameter, the function will return a new function that sums any number to the original argument. Let’s curry it!

1
2
3
4
5
var add = curry(function(a, b) {return a + b;});
 
var add42 = add(42);
add42(7); // => 49
add(42, 7) // => 49

There are multiple ways this curry function can be coded but the important thing here is to understand the concept. For different approaches refer to “How to correctly code a curry function“.

Conclusion

Functional programming provides us with a series of benefits that can give us leverage when creating understandable, reusable, parallel and scalable code. It’s by no means a better approach than object-oriented programming, it’s just another way of understanding problems that can be a better fit for some environments.

This blog post was aimed at showing the capacity of Javascript in producing such code (as it’s capable of producing OOP). If this has caught your interest there are a number of resources that you may find useful:

Related Belatrix content

Leave a comment