In this post we'll cover a couple techniques in Javascript that are common among functional languages: currying and partial application. You don't need a background in functional programming to understand these, so don't worry.

A quick review about functions...

So, I'll assume you have a basic understanding of functions in Javascript, including higher-order functions, closures and call & apply; if not, go review those topics quickly and come back.

Now that you're back, let's review a couple of important points before moving ahead.

Arity refers to the number of arguments a function can accept. This might be none, one (unary), two (binary) or more (polyadic). You can also have functions that take a variable number of arguments, (variadic functions).

Functions allow you to access their arity via the .length property of the function. The .length of a function never changes - it always matches the number of declared arguments for the function.

function howMany(a,b,c) {  
    console.log(howmany.length);
}

howMany(1,2);      // 3  
howMany(1,2,3,4);  // 3  

Obviously, it's up to you and your function to properly handle the cases of too few and too many arguments.

Variadic Functions are those functions which take a variable number of arguments.

Javascript allows us to access all the arguments passed to a function via the arguments variable made available inside a function's scope. This variable contains an array-like list of all the arguments pass to the function when it was called.

I say, array-like, because even though it's a list, it only has a .length and none of the other properties you'd expect of a real Array. You can access it via indexing [], get the .length and iterate over it using a loop construct - and that's about it.

But we can convert this into a 'real' array which will make the arguments list much more useful to us:

function showArgs() {  
   var args = [].slice.call(arguments);
}

The [].slice.call(arguments) is a short-handed way of doing Array.prototype.slice.call(arguments), we just take advantage of the use of an array literal.

In ES6 we can access and 'unpack' our arguments even more easily with the help of the spread/gather operator:

function howMany(...args) {  
   console.log("args:", args, ", length:", args.length);
}
howMany(1,2,3,4);  // args: [1,2,3,4], length: 4   (a "real" array)!  

With all that out of the way -- which I'm sure you knew already -- we can move on to our main topic!

Currying

Currying is the process of taking a function that accepts N arguments and turning it into a chained series of N functions each taking 1 argument.

If we had an add() function that accepted 3 arguments and returned the sum,

function add(a,b,c) { return a+b+c; }  

we can turn it into a curried function as follows:

function curriedAdd(a) {  
   return function(b) {
     return function(c) {
       return a+b+c;
     }
   }
}

How does currying work? It works by nesting functions for each possible argument, using the natural closure created by the nested functions to retain access to each of the successive arguments.

What we want is a way to easily convert an existing function that takes N arguments into its curried version without having to write-out each curried version of a function as we did with curriedAdd().

Let's see if we can decompose this and build something useful.

Writing a generic curry()

Ideally, this is the curry() function interface we'd like to design:

function foo(a,b,c){ return a+b+c; }  
var curriedFoo = curry(foo);

curriedFoo(1,2,3);   // 6  
curriedFoo(1)(2,3);  // 6  
curriedFoo(1)(2)(3); // 6  
curriedFoo(1,2)(3);  // 6  

Our curry() returns a new function that allows us to call it with one or more arguments, which it will then partially apply; up until it receives the last argument (based on the original function's arity) at which point it will return the evaluation of invoking the original function with all the arguments.

We know we can access the arity of a function using the .length property of the function. We can use this knowledge to allow us to know how many chained sequences of that function we need to call.

And, we'll need to store the original function passed in as well, so that once we have all the required arguments we can call the original function with the proper arguments and return its results.

Here's our first attempt:

function curry(fn) {  
  return function curried() {                           
    var args = [].slice.call(arguments);
    return args.length >= fn.length ?
      fn.apply(null, args) :
      function () {
        var rest = [].slice.call(arguments);
          return curried.apply(null, args.concat(rest));
      };
  };
}

Let's break this down in detail...

  • line 2 our curry function returns a new function, in this case a named function expression called curried().
  • line 3 every time this function is called, we store the arguments passed to it in args
  • line 4 if the number of arguments is equal to the arity of the original function, we have them all, so
  • line 5 return the invocation of the original function with all the arguments
  • line 6 otherwise, return a function that will accept more arguments that, when called, will call our curried function again with the original arguments passed previously combined with the arguments passed to the newly returned function.

Let's give this a try with our original add function from before.

var curriedAdd = curry(add);  
curriedAdd(1)(2)(3);  
// 6
curriedAdd(1)(2,3);  
// 6

Excellent! This seems to do exactly what we want it to do. However, suppose we had an object with functions that depended on the proper object being set to the calling context (this) of the function. Can we use our curry function to curry an object method?

var border = {  
  style: 'border',
  generate: function(length, measure, type, color) {
    return [this.style + ':', length + measure, type, color].join(' ') +';';
  }
};

border.curriedGenerate = curry(border.generate);

border.curriedGenerate(2)('px')('solid')('#369')  
// => "undefined: 2px solid #369;"

Uh oh. That's not what we wanted.

Using our curry() function as a method decorator1 seems to break the object context expected by the method. We'll have to retain the original context and be sure and pass it along to successive calls to the returned curried function.

function curry(fn) {  
    return function curried() {
        var args = toArray(arguments), 
            context = this;

        return args.length >= fn.length ?
            fn.apply(context, args) :
            function () {
                var rest = toArray(arguments);
                return curried.apply(context, args.concat(rest));
            };
    }
}

Let's try it again.

border.curriedGenerate(2)('px')('solid')('#369')  
// => "border: 2px solid #369;"

Got it! Now our curry() function is context aware and can be used in any number of situations as a function decorator.

Currying Variadic Functions?

So our current solution works and correctly retains the context when called, as long as those functions being curried only accept exactly the number of arguments they declare - no more, no less. This doesn't help us if we want to curry a function that has optional declared arguments or a variable number of arguments (variadic functions).

With variable argument functions, we need a way to tell our curry() function when it has enough arguments to evaluate the original function that it's currying.

Take the following functions

function max(/* variable arguments */) {  
  var args = [].slice.call(arguments);
  return Math.max.apply(Math, args);
}

function  range(start, end, step) {  
  var stop = Math.max(start, end),
      start = Math.min(start, end),
      set = [];

  // step is optional
  step = typeof step !== 'undefined' ? step : 1;

  for (var i=start; i <=stop; i+=step) {
      set.push(i);
  }  
  return set;
}

In the above, if we tried to use curry(max)(1)(2)(3) it evaluates too soon and we get a TypeError.

If we try to use curry(range)(1)(10) it never evaluates and simply stops by returning us a function that is still expecting another argument.

There is no feasible implementation of curry which will suffice for the example of our max() function which can take any number of arguments. Without an arity or a minimum number of arguments, there's no efficient way to determine when we should evaluate the original function with the arguments up to that point.

However, we can try to handle the case of optional, trailing arguments as in our range() example; and with minimal changes to our original curry() implementation.

We can modify our original curry() function to take an optional second argument which is the minimum number of arguments to curry.

function curry(fn, n) {  
  var arity = n || fn.length;
  return function curried() {
      var args = toArray(arguments), 
          context = this;

      return args.length >= arity ?
          fn.apply(context, args) :
          function () {
              var rest = toArray(arguments);
              return curried.apply(context, args.concat(rest));
          };
  };
}

Now, we can call curry(range, 2)(1)(10) as well as curry(range, 2)(1)(10,2). Unfortunately, though, we can't call it as curry(range, 2)(1)(10)(2), because as soon as it sees the minimum number of arguments, 2 in this case, it will return the results of evaluating the curried function.

What to do about Currying then?

It's clear from our examination above that currying in Javascript is definitely possible and useful. However, because Javascript allows any function to be variadic by nature, it becomes inefficient to implement a curry() function that can handle all possible cases.

Solution: If you're writing in a functional style, with unary and/or binary functions; and those functions take specific arguments that are declared, take advantage of currying. Otherwise, using our original implementation of curry() with the understanding that there are limitations surrounding functions with optional or variable arguments might be the best approach.

Partial Application

That was a lot of talking about currying; so, what is partial application?

Partial application means taking a function and paritally applying it to one or more of its arguments, but not all, creating a new function in the process.

Javascript already lets you do this with Function.prototype.bind()

function add3(a, b, c) { return a+b+c; }  
add3(2,4,8);  // 14

var add6 = add3.bind(this, 2, 4);  
add6(8);  // 14  

But, that sounds a lot like what our curry() function does internally. If you have curry(), you also have partial application!2

var add6 = curry(add3)(2)(4);  
add6(8); // 14  

The primary difference is in how you use them. We can implement a partial application function fairly easily (this is applying arguments from left to right)

// Apply left arbitrary number of arguments
function apply(fn /* partial arguments... */) {  
    var args = [].slice.call(arguments, 1);
    return function() {
        var _args = [].slice.call(arguments);
        return fn.apply(this, args.concat(_args));
    }
}

And we can call this, much like bind but without the initial context argument, like var add6 = apply(add3, 2, 4).

ES6 curry and apply implementations

To wrap things up, I promised to cover the ES6 implementations as well, so here is curry(),

function curry(fn) {  
    return function curried(...args) {
        return args.length >= fn.length ?
            fn.call(this, ...args) :
            (...rest) => {
                return curried.call(this, ...args, ...rest);
            };
    };
}

and here's our apply() function in ES6 as well.

// Apply left arbitrary number of arguments
function apply(fn, ...args) {  
    return (..._args) => {
        return fn(...args, ..._args);
    };
}

The ...(spread/gather) operator and => fat arrow functions simplify the amount of code we need to implement our previous ES5 versions of curry and apply; and, I think they make the implementation more clear and understandable as well.3

You can find more references on this topic from these great posts as well.


  1. A “function decorator” is a function that consumes a function and returns a decorated, or modified, version of the function it consumes. You can read up on function and method decorators here.

  2. As Reginald says in his post on the subject, "Well, if you have currying you don’t need partial application. And conversely, if you have partial application you don’t need currying."

  3. Read more about the ES6 spread/gather operator and fat arrow functions.