with Imagination: by Dustin Diaz

./with Imagination

A JavaScript, CSS, XHTML web log focusing on usability and accessibility by Dustin Diaz

JavaScript currying

Sunday, February 25th, 2007

Currying in JavaScript, in my own opinion, leads to clever programming. It is also one of the places in JavaScript where functional programming wins over object oriented practices. Sometime last year Dan Webb wrote a post on callbacks and partial application which essentially uses a pattern technique called currying. In his article, he gives a few examples which essentially prove the usefulness of currifed JavaScript.

callbacks in JavaScript (paraphrased code from danwebb.net)

// callback function declaration
function update(id) {
    return function(resp) {
        document.getElementById(id).innerHTML = resp.responseText;
    };
}

// currying in action
request('comment.php', update('item'));

Obviously there are implications here that currying is clever. So on that same token, I figured it would have been just as useful to write my very own JavaScript currier function. This was written nearly the same time Dan’s article came out, but I’m just now getting to sharing it. It looks like this:

a curry function in JavaScript

function curry (fn, scope) {
    var scope = scope || window;
    var args = [];
    for (var i=2, len = arguments.length; i < len; ++i) {
        args.push(arguments[i]);
    };
    return function() {
	    fn.apply(scope, args);
    };
}

This can be used in many ways. Here are a few:

practical usage of the curry function

/* add a curried function bound to a click event */
var el = document.getElementById('my-element');
el.addEventListener('click', curry(sayHello, el, 'Hello World from Dustin'), false);

function sayHello(msg) {
    alert(msg+'\n You clicked on '+this.id);
}

/* or to use it in the callback example */
request('comment.php', curry(update, window, 'item'));

/*
or let's say you're subscribing
to a custom event (eg. YAHOO.util.CustomEvent)
*/

var myEvent = YAHOO.util.CustomEvent(
    'shake it up',
    this,
    true,
    YAHOO.util.CustomEvent.FLAT
);
myEvent.subscribe(curry(doSomeThingCool, null, 'that', 'requires', 'these', args'));

You can also do a google search for javascript + curry for further information on other implemenations (no, I was not the first one to do this). Cheers.

30 Responses to “JavaScript currying”

  1. Binny V A

    The implementation of find/fold/map functions in Javascript
    http://invisibleblocks.wordpress.com/2007/02/23/functional-programming-in-javascript-and-ruby/

  2. Seb

    Just letting you know you’ve a couple of typos in that code, missing \ and missing ‘. I tried to email you rather than leaving a comment, but couldn’t actually find an email address or a contact form anywhere obvious….?

  3. Seb

    Oh, and the link to “callbacks and partial application” 404s :-)

  4. AJAX Matters Blog » Blog Archive » JavaScript currying

    [...] Dustin Diaz has written a post on the pattern technique called currying. For those of you not familiar with currying, it’s basically the transformation of an input into a new function. Dustin’s opinion is that: [currying]…leads to clever programming. It is also one of the places in JavaScript where functional programming wins over object oriented practices. [...]

  5. Mislav

    Nice writeup. This is the first time I hear of the term!

    Regarding the curry function implementation: why not slice instead of the for loop?

    var args = Array.prototype.slice.call(arguments,2)
  6. Mislav

    Come to think of it — your implementation is almost the same as Function.prototype.bind in the Prototype framework:

    Function.prototype.bind = function() {
      var __method = this, args = $A(arguments), object = args.shift();
      return function() {
        return __method.apply(object, args.concat($A(arguments)));
      }
    }
  7. Dustin Diaz

    @Seb: Sometimes wordpress does funny stuff to my code… for instance it stripped out the backslash. Anyway, if i was worried about typos, I’d be out of the blogging business ;)

    @Mislav: arguments is not a true array like you might think. The slice method will not work. Go ahead and try it. And yeah, the bind method does look similar, I just don’t know why it’s called bind… None the less Prototype has many programming idioms that other libraries don’t - and that’s pretty cool.

  8. Mike-2

    Corrected link.

  9. Dan Webb

    @Dustin: slice() will work if you call it the way Mislav does. I use that all the time. In fact, isn’t my entry on doing something similar the reason why you had me down as a mad tramp in your podcast? :)

  10. Ash Searle

    I’d guess the reason they call it ‘bind’ in prototype is because it’s not a general currying function (nor is the curry function presented here.) It’s purpose is to treat a function as a method of a given object (binding the function to the object)

    Currying is supposed to be used to assign fixed values to the first ‘n’ arguments of a multi-argument function. It’s nothing to do with method-calls (’scope’ is irrelevant.) Also, currying is not supposed to be used to create zero-argument functions.

    http://en.wikipedia.org/wiki/Currying

    Prototype’s ‘bind’ function is actually pretty close to general currying as it allows additional arguments to be passed in to the curried function by using args.concat($A(arguments))

    Also, as the ‘bind’ implementation shows - you don’t need to check for a valid ’scope’ before calling apply as ‘apply’ will do the checks for you (using global-scope if ’scope’ is null or undefined.)

    Final anally-retentive point: scope || window evaluates to window for the number 0, boolean false and the empty-string. Any one of them could be a legitimate object to call a method on.

  11. Dave

    @Dan & Mislav: Nice way to slice the arguments, unfortunately it won’t work in ie5 - call() isn’t supported. Of course apply() doesn’t work in ie5 either so I’m no better off really and sadly I do need to support ie5. Curse you ie5.

  12. Dave

    I spoke to soon

  13. justin

    Dustin, looks like Mislav just pasted in some code from the wikipedia article on Currying…
    http://en.wikipedia.org/wiki/Currying#JavaScript

    Slicing arguments probably works :D

  14. Philippe

    Be careful with the closure you are creating!

    PS: this is very similar to the Delegate technique in Flash Actionscript (which has adds a technique to avoid the closure).

  15. Mark Kahn

    My own implementation which allows a function to be re-called without having to re-call curry, ie:

    
    func.curry(arg1)(arg2, arg3);
    
    // or
    
    var x = func.curry(arg1);
    // ...
    var y = x(arg2);
    // ...
    y(arg3);
    
    Function.prototype.curry = function(argLength, argArray, args, forceCurry){
    	var _this = this, argArray = argArray?Array.copy(argArray):[], argLength = argLength||this.length;
    
    	if(args) Array.each(args, function(e){ argArray.push(e); });
    	if((argArray.length

    It requires two extra functions, Array.copy and Array.each:

    
    Array.copy = function(a){var n=[];for(var i=a.length-1; i>=0; i--){n[i]=a[i];}return n;};
    Array.each = function(a, fnc){for(var i=0; i
  16. Mark Kahn

    sorry, got stripped…

    
    Function.prototype.curry = function(argLength, argArray, args, forceCurry){
    	var _this = this, argArray = argArray?Array.copy(argArray):[], argLength = argLength||this.length;
    
    	if(args) Array.each(args, function(e){ argArray.push(e); });
    	if((argArray.length<argLength) || forceCurry){
    		return function(){
    			return _this.curry.apply(_this, [argLength, argArray, arguments]);
    		}
    	}
    	return this.apply(this, argArray);
    }
    
    Array.copy = function(a){var n=[];for(var i=a.length-1; i>=0; i--){n[i]=a[i];}return n;};
    Array.each = function(a, fnc){for(var i=0; i<a.length; i++){fnc(a[i]);}return a;};
    
  17. Bhasker V Kode

    I have my own version of currying in javascript , accompanied with a stress test that…well reveals a lot .

    http://bosky101.blogspot.com/2006/10/edited-currying-in-javascript-stress.html

    Keep Clicking,
    Bhasker V Kode

  18. Bhasker V Kode

    Hey Mr.Diaz,
    Love your screencasts,and long time reader of the blog as well .
    Now from the examples youve given -i really wonder if you need to curry for UI . at besti think it could be used for non-window painting events .(which means that each time you pass through the recusion, the window needs to repaint ) and ive faced cases where its even caused browser standstills and crashes.

    Instead how about a deferred event ?! i have another function called the IdempotentEvent which might be most suited for UI and DOM hacking . Its over at :

    http://bosky101.blogspot.com/2007/02/adding-idempotent-event-handling-to.html

    Keep Clicking,
    Bhasker V Kode

    Keep Clicking,
    Bhasker V Kode

  19. Peter Goodman

    Thank’s for this Dustin! After reading this I went and made a currying function for adding functions to events that had the event function auto-fixed.

  20. Adam van den Hoven

    A more indepth rendition of currying can be found at: http://www.svendtofte.com/code/curried_javascript/

  21. Currying in JavaScript

    [...] Dustin Diaz has a nice entry on currying in JavaScript a technique used often in languages such as LISP, Perl, and many others. [...]

  22. Diigo Diary Bookmarks 03/02/2007 « Benx Blog

    [...] JavaScript currying [...]

  23. links for 2007-03-03 « Benx Blog

    [...] JavaScript currying (tags: javascript currying *i_learning*) [...]

  24. JavaScript Currying Redux | CoryHudson.com

    [...] Currying in JavaScript is all the rage. There’s no shortage of code examples on how to do it. Regardless, currying is still a topic that many of us have a hard time truly wrapping our brains around. Let’s dig a little deeper. When we come out on the other side, we’ll have a little syntactic sugar for automagically currying functions that most of us have never seen before. [...]

  25. Brennan’s Blog » Blog Archive » Pairs, Triplets and Delegates, Oh My

    [...] These delegates are very useful. In the official documentation the block of code they define is called an anonymous method but I will also call it is a closure which are used heavily in Javascript and other dynamic scripting languages. In Javascript you use a closure to curry variables into an anonymous function. I am learning I can save a good deal of time with this style of coding. [...]

  26. » Presenting dsHistory: Another Way to Revisit the Past debugger;

    [...] As I stated earlier, dsHistory is pretty easy to use and was designed so that functions would be called as a user moved forwards and backwards through the history. Since it is based on functions, I highly recommend you use a currying helper function such as Dustin Diaz’s curry() or, my personal favorite, Prototype’s bind(). Use whatever works best for you. Anyway, check out the example code below. [...]

  27. » Presenting dsHistory: Another Way to Revisit the Past debugger;

    [...] Since it is based on functions, I highly recommend you use a currying helper function such as Dustin Diaz’s curry() or, my personal favorite, Prototype’s bind(). Use whatever works best for you. Anyway, check out the example code below. [...]

  28. Einar

    What is the recommended approach for avoiding memory leaks with currying when using a helper funtion like this?
    Since this will result in closures, IE is leaking a lot of memory.
    (Please don’t say ‘Use Firefox’).

    Einar

  29. Einar

    Einar, use Opera :))

  30. eXfer network » Another Curry Function for more Closure Options

    [...] There are a lot of curry functions examples out there so I decided I’d share mine as well. The code was inspired by a blog posting from Dustin Diaz who was in turn inspired by one from Dan Webb. Those posts can probably do an overall better job of explaining currying than I can so I’m not going to go in to the idea of currying in any great detail. So I’ll just say the currying pattern is useful for attaching data to a function in a way that avoids using global variables and simplifies the use of closure. [...]

Get "JavaScript Design Patterns"

"As a web developer, you'll already know that JavaScript™ is a powerful language, allowing you to add an impressive array of dynamic functionality to otherwise static web sites. But there is more power waiting to be unlocked--JavaScript is capable of full object-oriented capabilities, and by applying OOP principles, best practices, and design patterns to your code, you can make it more powerful, more efficient, and easier to work with alone or as part of a team."

Buy JS Design Patterns from Amazon.com Buy JS Design Patterns from Apress

Submit a Prototype

All content copyright © 2003 - 2007 under the Creative Commons License. Wanna know something? Just ask.

About | Archives | Blog Search

[x] close

Loading...

Submit a prototype

By checking this prototype I agree that I am not submitting false credentials, pornography, or a hate crime website. I also understand that by submitting my entry I may or may not be accepted, and if accepted, my entry may be taken down at any given time if I violate these terms.