contact Me

Use the form on the right to contact me.

You are welcome, to contact me regarding the topics of this page, my open source projects, or my work. Please use the contact form and leave a valid email address for me to respond to.

Thank you.

Egidestr. 9
44892 Bochum
Germany

/brain/dump

Random thoughts, bright ideas and interesting experiments. In short the ramblings of a fulltime nerd.

 

Currying functions in JavaScript - A generic approach

Jakob Westhoff

While preparing some slides for my jQuery workshop at this years WebTech Conference I was in need of different closure example. As I thought about complex ones currying came to my mind. Even though I actually never used this concept in JavaScript I quickly hacked a short function as a generic approach to introduce this feature to the language.

What is Currying?

Currying is a technique mostly known from functional programming languages. It has been invented by Moses Schönfinkel and Gottlob Frege. It has however been named after the inventor of the Haskell) programming language Haskell Brooks Curry.

Even though in theory it is a little bit more complicated, the practical realization of currying is quite simple. It is a transformation process which takes a function with multiple arguments as input and outputs a new function providing same behavior but lesser arguments. Binding some of the arguments to static values in the process. The example below provides a suitable demonstration of the idea:

function seq( start, end ) {
    var i;
    for( i = start; i < end; ++i ) {
        document.writeln( i );
    }
}

The function seq takes two arguments: start and end. Using this information it prints a sequence of numbers beginning at start and ending at end to the current document. To create a function with the same behavior, but a fixed start value, would be a perfect application of currying. As JavaScript has first-class functions and support for closures) one can easily create a wrapper around seq doing exactly this:

function fixSeqStart( start ) {
    return function( end ) {
        return seq( start, end );
    };
}

The function fixSeqStart can be used to create a new version of seq, which will only accept one argument, the end value. start has been frozen to a static value:

var seq10 = fixSeqStart( 10 );

// Print out numbers from 10 to 20
seq10( 20 );

A generic approach

The examples above present the idea behind currying. A usable implementation of this concept needs to be universal. Therefore it should be applicable for every function.

A generic implementation for any function is shown in the listing below:

function curry( fn /*, ... */ ) {
    var curryArgs = Array.prototype.slice.call( arguments, 1 );
    return function( /* ... */ ) {
        var newArgs    = Array.prototype.slice.call( arguments, 0 ),
            mergedArgs = curryArgs.concat( newArgs );
        return fn.apply( this, mergedArgs );
    }
}

The function curry can be used nearly the same way as the shown fixSeqStart. It can however be applied to any function, instead of only seq. In order to archive this it needs one more argument: the function to apply the currying to, which is passed in as first argument:

var seq10 = curry( seq, 10 );

Created this way the seq10 function does behave exactly the same way the function generated by fixSeqStart( 10 ) does.

An even more elegant solution to the problem is possible, by modifying the Function prototype and therefore changing what every function inherits:

Function.prototype.curry = function( /* ... */ ) {
    var args = Array.prototype.slice.call( arguments, 0 );
    args.unshift( this );
    return curry.apply( this, args );
};

Using the prototype based nature of JavaScript every function does now provide a curry function on its own, making the creation of the seq10 function even easier:

var seq10 = seq.curry( 10 );