Information


Blog Posts


Collections



Contact


Things Ian Says

Curried Javascript

In my previous blog entry, we looked at how functions are first class entities in Javascript, what an anonymous (or lambda) function is, and how we create and use closures.

We will now look at another functional technique, known as currying, which builds on those concepts.

Currying Functions

In some branches of mathematics, notably lambda calculus, a restriction is placed on functions that they can only accept one argument or parameter. This then allows analysis and reasoning about the functions.

Obviously, in our practical experience writing software, we frequently need functions which take more than one argument (e.g. to multiply two numbers together). Fortunately, there is a mathematical proof which says that any function taking multiple arguments can be converted into a series of functions taking one argument.

This process of converting from multiple arguments to single arguments is called currying (named after Haskell Curry) and is what we will be looking at here.

First, let’s write a simple function which takes two arguments and multiplies them together:

// Example of a simple function
function multiply (x, y) {
    return x * y;
}

And check that it works as expected:


// Expression
multiply(3, 4)

// Result
12

The way we curry a function is to create one function which takes the first parameter. That function then returns a second function which takes the second parameter, using a closure to carry the first parameter into the second function:

// Example of a curried function
function multiplier (x) {

    return function (y) {
        return x * y;
    };
}

So, in the above example, our multiplier function takes the parameter x and returns an anonymous function which takes the parameter y. This anonymous function returns the result of multiplying y by x (which is available within the closure).

To call the curried function, we need to pass the two parameters separately (since we have two functions). This is the same technique we used with our op function in the previous blog entry:

// Expression
multiplier(3)(4)

// Result
12

We can, if we like, pass only one parameter. In this case, it will return the inner function. This is known as partial application of the function:

// Expression
multiplier(3)

// Result
[Function]

Looking at what’s been returned, we can see the definition of the inner function, which in this example has x set to 3 within the closure (since the partial application had the first parameter as 3):

// Expression
multiplier(3).toString()

// Result
function (y) {
        return x * y;
    }

So, what is the point of this?

One use is to easily create new functions, based on the partial application of a curried function. If we wanted a double function, for example, we could generate that from our multiplier function (by passing it the parameter 2). We can assign that returned function to a variable, then that variable is our double function:

// Expression
double = multiplier(2)

// Result
[Function]

// Expression
double(10)

// Result
20

We can similarly create any function which multiplies its argument by some number:

// Expression
triple = multiplier(3)

// Result
[Function]

// Expression
triple(5)

// Result
15

// Expression
lakh = multiplier(100000)

// Result
[Function]

// Expression
lakh(14)

// Result
1400000

For completeness, let’s just see what happens when we try to pass in two parameters:

// Expression
multiplier(3, 4)

// Result
[Function]

As you can see, the second argument is ignored (because our curried function only expects one argument). We will take a look at how we can be more flexible about this later.

Another use of a curried function is to pass it into a map function to apply it to every element of an array. Suppose we define an array of numbers:

// Expression
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

// Result
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]

Assuming we have already defined a times8 function (by partial application of our curried multiplier function), we can pass that into map to allow us to multiply every element in the array by 8:

// Expression
numbers.map(times8)

// Result
[ 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 ]

In actual fact, we don’t need to define a times8 function, but can use the partial application directly as the parameter to map with the same result:

// Expression
numbers.map(multiplier(8))

// Result
[ 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 ]

So, we have seen two uses of curried functions. We will see an example later which demonstrates more uses.

Partial Application

For completeness, here is how we would write a multiplier function which supports both partial application with one parameter and direct multiplication with two parameters. We simply check the number of parameters which have been passed in and either return a result or a function as appropriate:

// Support for partial application
function multiplier (x, y) {

    if (arguments.length === 0) {
        return multiplier;
    }

    if (arguments.length === 1) {

        return function (z) {
            return x * z;
        };
    }

    return x * y;
}

Just accessing the function without any parameter list gives the function object itself:

// Expression
multiplier

// Result
[Function: multiplier]

If we call the function with an empty parameter list, we also get the function object itself. This gives us a consistent calling pattern:

// Expression
multiplier()

// Result
[Function: multiplier]

If we pass in one argument, we get back another function (i.e. we have partial application, just like before):

// Expression
multiplier(7)

// Result
[Function]

We can then add another parameter to our call (just like we did before) to arrive at a result:

// Expression
multiplier(7)(6)

// Result
42

However, the difference from our earlier examples is that we can now also pass in multiple parameters and get a result:

// Expression
multiplier(7, 6)

// Result
42

A Generic Curry Function

Creating curried functions by hand is a good way of understanding the principles, but our code would be more understandable if we could write a standard function and then curry it afterwards. Fortunately, because functions are first order entities in Javascript, we can write a function which takes a multi-parameter function as an argument and produces a curried version as its result.

To make it easier to understand how that works, here is an intermediate step. I have rewritten our earlier multiplier function in a slightly different way. It has the same functionality as before, but now makes use of the apply function and also uses the fact that the function object contains a length variable which says how many arguments the function is expecting.

Here is that rewritten function. The explanation of how it works is contained in the comments. It may help to refer back to the original multiplier function for comparison:

// Alternative version of earlier multiplied function
function multiplier (x, y) {

    /**
     * Javascript functions define an "arguments" object containing the
     * arguments passed in to the function.  We want this as an array,
     * and the following incantation achieves this (by slicing zero elements
     * from it).
     */
    var args = Array.prototype.slice.call(arguments, 0);

    /**
     * As before, if there are no arguments then return the function itself.
     */
    if (arguments.length === 0) {
        return multiplier;
    }

    /**
     * Here we make use of a feature of the function object.  It has a property
     * called "length" which contains the number of parameters the function is
     * expecting.  We use this in a comparison with the number of arguments
     * passed in to check whether this is a partial application.
     */
    if (arguments.length < multiplier.length) {

        /**
         * This is our partially applied function we will be returning
         */
        return function () {

            // Same trick as before to convert arguments list into an array
            var args2 = Array.prototype.slice.call(arguments, 0);

            /**
             * We use the "apply" method of the function object to invoke the
             * multiplier function here.  This takes an array as an argument
             * and then calls the function as if the values in the array had
             * been passed as the arguments to the function call.
             *
             * We already have our previous "args" from our closure, so we
             * concatenate that with this set of arguments to get the full
             * argument list.
             *
             * This is the same technique as we used originally (where "x" came
             * from the closure and "z" was passed in), just written in a
             * different way.
             */
            return multiplier.apply(null, args.concat(args2));
        }
    }

    // As before, with two arguments return the multiplication result
    return x * y;
}

The above function works exactly the same as our previous version, so I won’t bother providing example output. You can either trust me on this, or try the above code yourself in Node.

We’ve still got the currying logic and the function’s core behaviour wrapped up in a single function. Let’s fix that by creating a multiply function which performs the actual multiplication and then use that in our curried multiplier function. I’ve removed the earlier comments to make it more compact:

// Using external "multiply" function in multiplier function

function multiply (x, y) {
    return x * y;
}

function multiplier () {

    var args = Array.prototype.slice.call(arguments, 0);

    if (arguments.length === 0) {
        return multiplier;
    }

    if (arguments.length < multiply.length) {

        return function () {
            var args2 = Array.prototype.slice.call(arguments, 0);
            return multiplier.apply(null, args.concat(args2));
        }
    }

    return multiply.apply(null, args);
}

So now we have achieved separation of concerns. We have one function which takes care of how we multiply and one which takes care of how we curry.

The next obvious step is to make the curry function generic. We will rename it (to curry) and pass in the function to curry as a parameter. The curry function will then return a curried version of the function passed in:

// Generic curry function
function curry (fn) {

    var curriedFn = function () {
        var args = Array.prototype.slice.call(arguments, 0);

        if (arguments.length === 0) {
            return curriedFn;
        }

        if (arguments.length < fn.length) {

            return function () {
                var args2 = Array.prototype.slice.call(arguments, 0);
                return curriedFn.apply(null, args.concat(args2));
            }
        }

        return fn.apply(null, args);
    }
    return curriedFn;
}

We can invoke our curry function in the way most useful to us, for example:

// Curried function from pre-existing function
var multiplier = curry(multiply);

// Curry function at definition time
var multiplier = curry(function (x, y, z) {
    return x * y * z;
});

// Map partially applied function across an array
var double = multiplier(2);
values.map(double);

// Perform partial application as part of mapping
values.map(multiplier(2));

// Curry function at map time
values.map(curry(multiply)(2));

More importantly, because we have made it a generic function, it is no longer limited to handling two arguments. Here is an example with a five argument function and the different ways in which it can be partially applied.

First we define a suitable five argument function:

// Expression
add = function add (a, b, c, d, e) {return a + b + c + d + e;}

// Result
[Function: add]

// Expression
add(1, 1, 2, 3, 5)

// Result
12

Now we curry it and invoke it:

// Expression
add = curry(add)

// Result
[Function: curriedFn]

// Expression
add(1, 1, 2, 3, 5)

// Result
12

// Expression
add(1)(1, 2, 3, 5)

// Result
12

// Expression
add(1)(1)(2)(3)(5)

// Result
12

// Expression
add(1)(1)(2)(3, 5)

// Result
12

// Expression
add(1)(1, 2)(3, 5)

// Result
12

Note that the above is intended as an instructional exercise. For most real use, it is generally better to use a pre-existing currying module than to write your own.

Summary

This blog entry has covered both curried functions and partial application. It has demonstrated how to do this manually and has shown how to write a function which can curry other functions.

In the next blog entry we will look at an example application of the functional principles we have covered in these two blog entries. We will also see how functional techniques make it easier to work with promises.