JS - Currying

by Jason Aden

JavaScript

// Crockford's example
// make an add1 method, based on add

// First... the curry method
// extends Function object prototype with a new method
// uses a closure to remember the args
Function.prototype.curry = function () {

    // create a reference to the current function 
    // and the arguments (as an array)
    var fn = this,
        args = Array.prototype.slice.call(arguments);

    // return the function, which will now be invoked
    // with this context
    // and the arguments provided are tacked onto the beginning
    // of the arguments passed to the original function
    return function () {
        return fn.apply(this, args.concat(
        Array.prototype.slice.call(arguments)));
    };
}

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

var add1 = add.curry(1);

console.log("Add1: ", add1(5));

// Partials
// John Resig/Oliver Steele take this a step further
// Ability to fill in missing arguments for a partial
/*
Function.prototype.partial = function () {

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

    return function () {
        var arg = 0;
        // now we are looping through each argument
        // and if the argument is undefined, we check for
        // arguments passed to the curried function to fill it in
        for (var i = 0; i < args.length && arg < arguments.length; i++) {
            if (args[i] === undefined) {
                args[i] = arguments[arg++];
            }
        }
        return fn.apply(this, args);
    };
};

// create a default 10 ms function
var delay = setTimeout.partial(undefined, 10);
/**/

// Partials with bind()
// Using bind() (es5) makes this trivial
/*
var add10 = add.bind(undefined, 10);
console.log("Add10: ", add10(1));
/**/