01 July 2014

“OMG another curry article!?”

Got it out of your system? Cool. Let’s continue.

Functional programming makes heavy use of partial application and its simpler cousin, curry. I’m not here to rehash the debate over conflating terms, just offer an alternative pattern for adding curry to your application in es5 or es6 without modifying the native prototypes.

function curry( arg ) {
    var fn = this;
    function curried() {
        var args = [arg];
        args.push.apply( args, arguments );
        return fn.apply( this, args );
    }
    curried.curry = curry;
    return curried;
}

To use this method, you need to add it to a function, like this:

//start with a normal fn
function add( a, b ) {
    return a + b;
}

//add the curry capability
add.curry = curry;

//use curry
add.curry( 1 ); // this is a fn

//invoke a curried fn
add.curry( 1 )( 2 ); // 3

curry adds itself to the returned function when you use it, so its chainable.

//we can chain it!
add.curry( 1 ).curry( 2 )(); // 3

//additional parameters get ignored, as they should
add.curry( 1 ).curry( 2 ).curry( 3 )( 4 ); // 3

We can also still use call and apply as we normally would.

function addThis( a, b ) {
  return this + a + b;
}
addThis.curry = curry;

addThis.curry( 1 ).curry( 2 ).call( 3 ); // 6
addThis.curry( 1 ).curry( 2 ).apply( 0, [3] ); // 6

Our implementation gets even simpler using es6’s rest and spread operators

function curry( arg ) {
    var fn = this;
    function curried( ...args ) {
        return fn.apply( this, [arg, ...args] );
    }
    curried.curry = curry;
    return curried;
}

See the rest of the gist for tests (es6).

EDIT: I turned this into an npm module.



Discussion:

blog comments powered by Disqus