Currying is a fundamental tool in functional programming, a programming pattern that tries to minimize the number of changes to a program’s state (known as side effects) by using immutable data and pure (no side effects) functions.

Currying

Currying is the process of taking a function with multiple arguments and returning a series of functions that take one argument and eventually resolve to a value.

Here’s a simple example to illustrate it using the _.curry function from Lodash (we’ll build our own curry function shortly):

function volume(l, w, h) {
  return l * w * h;
}

const curried = _.curry(volume);

volume(2, 3, 4); // 24
curried(2)(3)(4); // 24

The original function volume takes three arguments, but once curried we can instead pass in each argument to three nested functions.

In other words, currying has effectively done this:

function volume1(length) {
  return function(width) {
    return function(height) {
      return height * width * length;
    }
  }
}

volume1(2)(3)(4); // 24

If you’re confused how the innermost function has access to the variables in outer functions, learn more about closures and scoping in JavaScript.

Arity

As you may have noticed, it’d be nice to have a way to refer to the number of parameters each function expects. It terms out there’s a fancy word for this: arity. A given function can have zero, one (unary), two (binary), three (ternary), or more (polyadic) parameters it expects.

Write your own curry function

Now it’s time to write our own curry function, which is a bit tricky. Fortunately ES6’s spread operator and arrow syntax help simplify things.

To start, we know curry accepts a function as well as a variable number of parameters:

var curry = (fn, ...args) => ...

Next we need to know how many arguments (the “arity”) our function expects. If the number of arguments we already have equals the number expected, we call the function. Otherwise, we return a new function.

We can obtain both values using the length property of a function:

var curry = (fn, ...args) =>
  (fn.length <= args.length) ...

Now the final step. If the value of arguments equals the value expected, we simply call the function fn(...args). But to return a new function and add it to our nested list, we store a series of functions which we can call ...more.

var curry = (fn, ...args) =>
  (fn.length <= args.length) ?
    fn(...args) :
    (...more) => curry(fn, ...args, ...more);

Conclusion

It takes a while to wrap your head around functional programming and currying. But it’s worth the effort.

To learn more, I highly recommend the free book Professor Frisby’s Mostly Adequate Guide to Functional Programming or any talks by its author Brian Lonsdorf. Kyle Simpson, the author of the You Don’t Know JS Series also has an online course, Functional-Light JavaScript, on the topic designed for beginners.