views:

300

answers:

4

A friend of mine and I were having a discussion regarding currying and partial function application in Javascript, and we came to very different conclusions as to whether either were achievable. I came up with this implementation of Function.prototype.curry, which was the basis of our discussion:

Function.prototype.curry = function() {
    if (!arguments.length) return this;

    var args = Array.prototype.slice.apply(arguments);
    var mmm_curry = this, args;

    return function() {
     var inner_args = Array.prototype.slice.apply(arguments);
     return mmm_curry.apply(this, args.concat(inner_args));
    }

}

Which is used as follows:

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

var karahi = vindaloo.curry(1);
var masala = karahi(2);
var gulai = karahi(3);

print(masala);
print(other);

The output of which is as follows in Spidermonkey:

$ js curry.js
3
4

His opinion was that since the Javascript function primitive does not natively support "partial function application", it's completely wrong to refer to the function bound to the variable karahi as partially applied. His argument was that when the vindaloo function is curried, the function itself is completely applied and a closure is returned, not a "partially applied function".

Now, my opinion is that while Javascript itself does not provide support for partial application in its' function primitives (unlike say, ML or Haskell), that doesn't mean you can't create a higher order function of the language which is capable of encapsulating concept of a partially applied function. Also, despite being "applied", the scope of the function is still bound to the closure returned by it causing it to remain "partially applied".

Which is correct?

+1  A: 

You should check out Curried JavaScript Functions. I haven't completely wrapped my head around his curry function, but it might have your answer.

Edit: I would agree with your assessment, however.

Zach
+1  A: 

I think it's perfectly OK to talk about partial function application in JavaScript - if it works like partial application, then it must be one. How else would you name it?

How your curry function accomplishes his goal is just an implementation detail. In a similar way we could have partial application in the ECMAScript spec, but when IE would then implement it just as you did, you would have no way to find out.

Rene Saarsoo
+3  A: 

Technically you're creating a brand new function that calls the original function. So if my understanding of partially applied functions is correct, this is not a partially applied function. A partially applied function would be closer to this (note that this isn't a general solution):

vindaloo.curry = function(a) {
    return function(b) {
        return a + b;
    };
};

IIUC, this still wouldn't be a partially applied function. But it's closer. A true partially applied function would actually look like this if you can examine the code:

function karahi(b) {
    return 1 + b;
};

So, technically, your original method is just returning a function bound within a closure. The only way I can think of to truly partially apply a function in JavaScript would be to parse the function, apply the changes, and then run it through an eval().

However, your solution is a good practical application of the concept to JavaScript, so practically speaking accomplishes the goal, even if it is not technically exact.

Michael Johnson
You talk about "technically" vs. "practically", but what about "theoretically"? Is "partial function application" a theoretical concept or a technical one? If we imagine the curry/partial function as a "conceptual function" (not "Javascript function"), does it not get "partially applied"?
Nathan de Vries
I think "partial application" is a conceptual thing, not an implementation thing.
trinithis
+1  A: 

The technical details don't matter to me - if the semantics remain the same and, for all intents and purposes, the function acts as if it were really a partially-applied function, who cares?

I used to be as academic about things, but worrying about such particulars doesn't get real work done in the end.

Personally, I use MochiKit; it has a nice partial() function which assists in the creation of such. I loves it.

Jason Bunting