How do you curry any javascript function of arbitrary arity?
I believe that you could simply use Function.prototype.bind
. That gives you all the flexibility you need, wheter you want the result of the function right away or simply push another value into the arguments until you decide to execute.
function sum() {
return [].reduce.call(arguments, function (c, n) {
return c + n;
});
}
sum(1, 2); //3
var sum2 = sum.bind(null, 1, 2);
sum2(); //3
var sum3 = sum2.bind(null, 3);
sum3(); //6
You could also use a helper function like:
function curry(fn) {
var c = curry.bind(this, fn = fn.bind.apply(fn, [this].concat([].slice.call(arguments, 1))));
c.exec = fn;
return c;
}
curry(sum, 1, 2)(3)(4, 5)(6, 7, 8).exec(); //36
Also this is very flexible as you do not have to chain, you can re-use the same curried function.
var sumOnePlus = curry(sum, 1);
sumOnePlus.exec(2); //3;
sumOnePlus.exec(3); //4;
Here's my attempt:
function curry(fn, len) {
if (typeof len != "number")
len = fn.length; // getting arity from function
return function curried() {
var rlen = len - arguments.length;
if (rlen <= 0) // then execute now
return fn.apply(this, arguments);
// else create curried, partially bound function:
var bargs = [this]; // arguments for `bind`
bargs.push.apply(bargs, arguments);
return curry(fn.bind.apply(fn, bargs), rlen);
};
}
This does not partial application (which is easy in JS with the bind
method), but true functional currying. It works with any functions of arbitrary, but fixed arity. For variadic functions you would need a different execution trigger, maybe when no arguments are passed any more or an exec
method like in @plalx' answer.