Curry: cooking up tastier functions

Currying allows you to easily create custom functions by partially invoking an existing function. Here’s a simple example:

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

var addTen = add.curry(10); //create function that returns 10 + argument
addTen(20); //30

Generally, curry returns a copy of the invoking function, with its first n arguments pre-assigned with the arguments passed by the curry invocation.

The curry function does not exist in native JavaScript, but it’s easy to write your own. Here I’m augmenting function’s prototype with an implementation based on the Prototype framework. (Notice I’m also throwing in a toArray function for convenience. This is because function’s arguments property is not a true array, and we need it to work with array’s concat function)

function toArray(enum) {
    return Array.prototype.slice.call(enum);
}

Function.prototype.curry = function() {
    if (arguments.length<1) {
        return this; //nothing to curry with - return function
    }
    var __method = this;
    var args = toArray(arguments);
    return function() {
        return __method.apply(this, args.concat(toArray(arguments)));
    }
}

The returned function expects to be invoked with additional argument(s) which it will concatenate with the argument(s) it got from the curry function.

In case you were wondering: we could provide the curry function with all the arguments required by the calling function:

//not very useful example
var make5 = add.curry(2,3);
make5(); //5

//better example
var sayHello = alert.curry("Hello!");
friendlyDiv.onmouseover = sayHello;

The add function is very basic, but as the logic of a function gets more complex, the value of re-applying that logic to distinct parameters becomes more apparent.

Consider a function that returns the RGB index (in hex) for the color that falls at a given point in the transition between two given colors (specified either by name named or RGB hex)

var getColorBetween = function(transitionFactor, color1, color2) {
    //..
}

getColorBetween(0.5, "red", "green"); //<span style="color:#7f4000;">"#7f4000"</span>

If we want to create a series of fall colors, we could experiment by creating a function that returns colors that fall (no pun) 25% of the way between orange and the given color:

var getFallColor = getColorBetween.curry(0.25, "#ff8000");

reddishFallColor = getFallColor("red"); //<span style="color:#ff6000;">"#ff6000"</span>
yellowishFallColor = getFallColor("yellow"); //<span style="color:#ff9b00;">"#ff9b00"</span>
brownishFallColor = getFallColor("#800000"); //<span style="color:#df7000;">"#df7000"</span>

Here’s another example that generates various conversion functions

var converter = function(ratio, symbol, input) {
    return [(input*ratio).toFixed(1),symbol].join(" ");
}

var kilosToPounds = converter.curry(2.2,"lbs");
var litersToUKPints = converter.curry(1.75, "imperial pints");
var litersToUSPints = converter.curry(1.98, "US pints");
var milesToKilometers = converter.curry(1.62, "km");

kilosToPounds(4); //8.8 lbs
litersToUKPints(2.4); //4.2 imperial pints
litersToUSPints(2.4); //4.8 US pints
milesToKilometers(34); //55.1 km

Now, go forth and curry.

About these ads

19 thoughts on “Curry: cooking up tastier functions

  1. Something like this should work, too:

    var converter = 
        function(ratio) {
            return function(symbol) {
                return function(input) {
                     return [(input*ratio).toFixed(1),symbol].join(" ");
                }
            }
        }
    
    var kilosToPounds = converter(2.2)("lbs");
    kilosToPounds(4); //8.8 lbs
  2. Providing the curry function with all arguments is useful when you want to use the resulting function as a callback. You can do something like:

    new Ajax.Request(url, { onSuccess: alert.curry(“success!”) })

    • Thank Vladimir – yes, its really useful as a shorthand / more readable alternative to pre-assigning variables in anonymous function through closures. I find myself using define-all-args currying more and more

  3. Pingback: How evil is eval? By Angus Croll | Little knowledge is dangerous

  4. Pingback: links for 2010-08-06 « sonofbluerobot

  5. Great post, this is useful; I would like to mention though that this is a common misunderstanding of the definition of currying. This is a function to partially apply arguments to another function. Currying is actually taking a multiple argument function and returning a “higher-order” function. In this sense, a real curry shouldn’t take parameters.

    This confusion comes about because functions are automatically curried in functional languages, which allows partial applications. People then go on to say “that function is curried”, but they really meant “that curried function has been partially applied” or simply “that function is partially applied”.

    Difference illustrated below:


    var foo = function(a, b) { return a + b; };
    foo.partiallyApply(2); // equivalent to function(b) { return 2 + b; }
    foo.curry(); // equivalent to function(a) { return function(b) { return a + b; }; }
    foo.curry()(2); // equivalent to foo.partiallyApply(2)

    • Hans I agree. In pure functional language like Haskell (named for Haskell Curry so they should know ;-) ) the definition you supply is correct. In JavaScript, however, the definition I use is generally accepted as the convention (including by Resig and Crockford :-) )

      • The curry function

        Function.prototype.curry = function () {
        	var method = this,
        		i = 0,
        		len = this.length,
        		args = [];
        	
        	function f() {
        		args.push(arguments[0]);
        		if (++i < len) {
        			return f;
        		} else {
        			method.apply(this, args);
        		}
        	};
        	return f;
        }
        
  6. Pingback: Currying and Partial Applications in F#, Javascript and C# | theburningmonk.com

  7. I actually tested this type of function out today from a new JavaScript library called jPaq. This is definitely a useful function. The cool thing about jPaq is I can download a library of only the functions that I need.

  8. Pingback: [번역] 함수 선언 vs 함수 표현 (Function Declarations vs. Function Expressions) | Inside jQuery

  9. Pingback: dynamic function arguments in array - Programmers Goodies

  10. Technically `function currying` is the pattern to decompose a function with n arguments into a chain of function calls; each with 1 of the n arguments.

    But I fallback to thinking `currying` as similar to `partial applications`. Currying also means `prepare`… So we can think of function currying as preparing for future function calls based on initial preparation with 1-n captured arguments.

    The great thing about the generalized concept is that ANY of the [original] function’s arguments can be pre-captured; in any order. The resulting function publishes a new function that has a reduced set of arguments.

    This becomes immensely useful with sorting, searching, scope captures, and more. Instead of using classes to preserve state/data, I use currying/partial applications to capture argument values. Very functional solution…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s