The If Works This dirt was a building before

Self-currying JavaScript functions

I’m telling you, this language keeps surprising me. You’ll need Prototype for this one.

Function.prototype.toSelfCurrying = function(n) {
  n = n || this.length;
  var method = this;
  return function() {
    if (arguments.length >= n) return method.apply(this, arguments);
    return method.curry.apply(arguments.callee, arguments);
  };
};

Make a simple function:

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

And curry away:

var add = adder.toSelfCurrying();

add(1)(2)(3)  // --> 6
add(7,8)(23)  // --> 38

Every call to add returns a curried version of add, until the required number of arguments have been supplied. When all arguments are present, you get a return value.


15 Comments

:) super cool hack. This shows the power of Javascript.

Posted by RStankov on 12 December 2007 @ 9am

You, sir, are the JavaScript devil. Nice work.

Posted by cwmonkey on 6 February 2008 @ 2am

Interesting! You have implemented the curry() function in javascript. Now, can you implement uncurry?

Posted by Peter Goodman on 6 February 2008 @ 3am

Sweet!. Javascript never seizes to surprise me. Very neat hack!

Posted by Abhijith on 6 February 2008 @ 5am

This is pretty cool! Technically speaking, I think this is “partial application” though and not currying.

Posted by HarryHunt on 6 February 2008 @ 9am

Indeed, this is partial application, not currying. Check http://www.haskell.org/haskellwiki/Currying for a quick and nice explanation

Posted by Ricardo Herrmann on 6 February 2008 @ 4pm

Ricardo, thanks for the link. Very helpful, so much so that I actually understood it without ever having used Haskell. Trouble is, Prototype’s curry() method is really partial application, but it’s taken the name so I needed to call my method something else.

Posted by James Coglan on 6 February 2008 @ 5pm

Very nice. And I like the picture and color of your blog

Peace
-stephan

Posted by Stephan Schmidt on 6 February 2008 @ 6pm

In case automatic trackback does not work properly, I will comment here as well. In my post at http://www.barklund.org/blog/2008/02/06/self-partially-applying-javascript-functions/ I discuss and improve on the above as well as implement it in native JavaScript as well as with the MochiKit framework.

But all in all, a very nice trick and a very nice idea. Thanks for the inspiration :)

Posted by Morten Barklund on 6 February 2008 @ 9pm

Just to clear up a couple of things: first, as defined in the Haskell language:

“Currying is the process of transforming a function that takes multiple arguments into a function that takes just a single argument and returns another function if any arguments are still needed.” – Haskell docs

This is what toSelfCurrying() does. However, according to Wikipedia:

“In computer science, currying, invented by Moses Schönfinkel and Gottlob Frege, is the technique of transforming a function that takes multiple arguments into a function that takes a single argument (the other arguments having been specified by the curry).” – Wikipedia

So there’s room for debate. It looks to me (naive as I am) as though Haskell is a special case because all Haskell functions are single-argument functions, so you need to use currying to build multi-argument functions. The discrepancy seems to be over whether pre-set arguments are set with the currying operation. toSelfCurrying() is essentially equivalent to currying in Haskell, while Prototype’s curry() is more in tune with the Wikipedia definition, taking into account JavaScript’s flexibility. Given that the word ‘currying’ is a reference to Haskell B. Curry, I’m inclined to side with the Haskell definition of currying, while referring to Prototype’s curry() as partial application. Apart from anything, partial() and curry() just seem like better nomenclature than curry() and toSelfCurrying().

Second, this blog’s design is the handy work of my colleague Ben Eastaugh (extralogical.net). Funny story, I’d been using this blog template for months before I moved to my current job. A little while after I started, we hired Ben and it emerged he was behind my blog design. Small world.

Posted by James Coglan on 6 February 2008 @ 11pm

Actually this concept does more than curry. If curry is transforming a multifunction into a series of single argument function, then this is achieved by the above – among other things. Because as another commenter asks: “how to implement uncurry?”.

But the function returned is all spices! It works with any of 1-n arguments and will just collect and remember how many has been given and return a (n-”given arguments”)-ary function that still can accept less than this value. The resulting function is thus both curried and uncurried.

If you want to create uncurry, which returns a function, that only can accept all arguments (or will invoke the function with only the given arguments), then you simply need to store the function reference on the function instance (as in my implementation) and return this from the given function:

function curry(f, n) {
  var g = function() {
    var c = arguments.callee;
    if (c._len <= arguments.length)
      return c._func.apply(null, arguments);
    return bind(c, arguments);
  }
  g._len = n || f.length;
  g._func = f;
  return g;
}
function uncurry(f) {
  return f._func || f;
}
var a = function(a,b) {return a+b;}
assert(a == uncurry(curry(a)));

It might not be interesting at all, but it works.

Regarding the discussion of the definition of curry, I was reading more along the lines of the Wikipedia-definition, but I see your point. The Prototype function curry is called partial in MochiKit anyway. We might need a new term for this kind of function, as it somehow defies current definitions. Brave new world ;)

Posted by Morten Barklund on 7 February 2008 @ 3pm

“multifunction” => “multi argument function” of course.

And another funny thing is, that the returned function of course also collect arguments when invoked without any at all:

add()()()()(1)()()()(2,3);

Very silly, but conceptually sound.

Posted by Morten Barklund on 7 February 2008 @ 3pm

but why should I care about this stuff?! Except for constructing weird syntax function calls or whatever. How does it help me?

Posted by ExcuseMe on 8 February 2008 @ 5pm

Hi. Maybe it is helpful to consider that it is based on λ-calculus, and in λ-calculus, functions can only take one argument. Therefore, all functions in Haskell take one argument. So for functions with more than one argument, currying is necessary.

Posted by Chris Done on 16 March 2008 @ 2pm

[...] Self-currying JavaScript functions [...]

Posted by 網站製作學習誌 » [Web] 連結分享 on 25 November 2009 @ 2am

Leave a Comment