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.







14 Responses to “Self-currying JavaScript functions”

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

RStankov added these pithy words on Dec 12 07 at 9:14 am

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

cwmonkey added these pithy words on Feb 06 08 at 2:01 am

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

Peter Goodman added these pithy words on Feb 06 08 at 3:53 am

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

Abhijith added these pithy words on Feb 06 08 at 5:48 am

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

HarryHunt added these pithy words on Feb 06 08 at 9:00 am

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

Ricardo Herrmann added these pithy words on Feb 06 08 at 4:52 pm

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.

James added these pithy words on Feb 06 08 at 5:35 pm

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

Peace
-stephan

Stephan Schmidt added these pithy words on Feb 06 08 at 6:01 pm

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 :)

Morten Barklund added these pithy words on Feb 06 08 at 9:43 pm

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.

James added these pithy words on Feb 06 08 at 11:33 pm

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 ;)

Morten Barklund added these pithy words on Feb 07 08 at 3:18 pm

“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.

Morten Barklund added these pithy words on Feb 07 08 at 3:22 pm

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

ExcuseMe added these pithy words on Feb 08 08 at 5:13 pm

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.

Chris Done added these pithy words on Mar 16 08 at 2:22 pm

Leave a Reply