Goal of this post

The goal of this post is to be able to call any javascript function partially. For example, it would mean that if we had a function like:

function add (x, y, z) {
  return x + y + z;
}

We would like to be able to do the following:

var partialAdd = add(1); // yields a function that needs 2 more arguments
var result = partialAdd(2, 3);  // yields 6

It means that we can call the function however we want (fully or partially):

add(1, 2, 3); // yields 6
add(1)(2)(3); // yields 6

Starting point

We will start by looking at a function found online here.

function schonfinkelize(fn) {
     var slice = Array.prototype.slice,
        stored_args = slice.call(arguments, 1);
     return function () {
        var new_args = slice.call(arguments),
              args = stored_args.concat(new_args);
        return fn.apply(null, args);
     };
}

This is a interesting function and a good attempt at making functions partially in javascript. The basic idea of this function is that it takes the original arguments and returns a function that waits for the remaining arguments. You can use it this way:

var addSecondHalf = schonfinkelize(add, 1); // yields a function
addSecondHalf(2, 3); // yields 6 

The issue with this function is that we can't do something like:

schonfinkelize(add, 1)(2)(3); // Doesn't work

The reason it doesn't work is because schonfinkelize is not called recursively by looking if we have enough arguments to call the function. In order to make it work, we would have to do something like the following:

schonfinkelize(schonfinkelize(add, 1)(2))(3);  // yields 6

The path to the solution

The first thing we need to think about is how do we know if we have enough arguments to call the function? It turns out javascript has this built-in. Every function in javascript has the attribute length, which returns the number of arguments a function is expecting. So in our case:

add.length  // yields 3

With this information, we know that the base case of our recursive call will be called if we have enough arguments to call the function. With this in mind, let's look at a first solution.

function partialApply(fn) {
    var slice = Array.prototype.slice;
    var curr_args = slice.call(arguments, 1);
    if(fn.length > curr_args.length) {
        return function() {
            var new_args = slice.call(arguments);
            var args = curr_args.concat(new_args);
            return partialApply.apply(null, [fn].concat(args));
        }
    }
    else {
        return fn.apply(null, curr_args);
    }
}

So what does this function do exactly? We recursively call partialApply as long as we don't have enough arguments and the base case is called and we have enough or them. This function allows us to do something like:

partialApply(add, 1)(1)(2); // yields 4
partialApply(add)(1)(1)(2); // yields 4
partialApply(add)(1, 1)(2); // yields 4
partialApply(add, 1, 1, 2); // yields 4

Using the function prototype

This is great, but it feels awkward to have to pass the function as a parameter, wouldn't it be nice if we could do:

add.partialApply(1)(1)(2); // yields 4
add.partialApply(1, 1)(2); // yields 4
add.partialApply(1, 1, 2); // yields 4

The solution is very similar to the above but it will be bound to the function prototype:

Function.prototype.partialApply = function() {
    var fn = this;
    var slice = Array.prototype.slice;
    var curr_args = slice.call(arguments);
    if(fn.length > curr_args.length) {
        return function () {
            var new_args = slice.call(arguments);
            var args = curr_args.concat(new_args);
            return fn.partialApply.apply(fn, args); 
        }
    }
    else {
        return fn.apply(null, curr_args);
    }
};

In this function, we utilize the fact the javascript functions are first-class objects. In effect, any function is an instance of the Function prototype and therefore will have access to our function partialApply. The "this" keyword in javascript refers to the instance calling that function. The base case remains unchanged. It gets interesting when we look at the recursive call. The return statement is the following:

return fn.partialApply.apply(fn, args);

We can't simply call partialApply, we need to apply it because we only have access to the arguments in the form of an array. The other interesting part of this line is that we have to pass in fn as the first argument, since it defines what "this" will be in the function call. If we simply did:

return fn.partialApply.apply(null, args);

It would yield the error ("Cannot read property 'apply' of undefined"), since we would not bind this to the right function in the recursive call.

Usage

So now, how can I make it so all my functions can be partially applied? You can simply call .partialApply() on any function declaration you make. It looks like this.

var add = function(x, y, z) {
    return x + y + z;
}.partialApply();
var a = add(1, 2, 3); // yields 6
var b = add(1)(2)(3); // yields 6
var c = add(1)(2, 3); // yields 6

So this is how you curry your functions in JavaScript!

Thank you for reading.