How is the curry function supposed to work?
I have a function that looks like this:
function curry(fn) {
var args = [].slice.call(arguments, 1);
return function() {
return fn.call(this, args.concat([].slice.call(arguments)));
};
}
I always thought that the function should look and should work like:
function add(a, b, c, d) {
return a+b+c+d;
}
curry(add, 1, 2)(3, 4);
but the Wikipedia article says that
it can be called a chain of functions, each with one argument
so the curry should look like this:
function curry(fn) {
var args = [];
return function curring() {
args = args.concat([].slice.call(arguments));
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return curring;
}
};
}
and will be used like this:
function add(a, b, c, d) {
return a+b+c+d;
}
curry(add)(1)(2)(3)(4);
I'm right?
source to share
Strictly speaking, currying converts a function with many arguments into a series of functions, each with one single argument, like in your second function curry
:
-
If you call all of them (in a chain), you end up with a complete function application that gives the same result as the original function:
curry(add)(1)(2)(3)(4)
returns the same asadd(1, 2, 3, 4)
, i.e.10
-
If you only call a subset, you get a partially applied function:
-
addOne = curry(add)(1);
-
addOneAndTwo = addOne(2);
-
addOneAndTwo(3)(4)
returns10
-
In Javascript, currying is usually used synonymously with partial application, as in your first function curry
. To paraphrase the Prototype Documentation :
curry curries (burns in) function arguments, returning a new function that, when called with a call, passes the original pass into the arguments in curry (along with any new ones).
For a more detailed explanation, see What is the Difference Between Currying and Private Application .
Below is a working implementation of a true curry function in javascript by Evan Borden.
A few caveats:
-
Your first function
fn.call
is wrong. You should usefn.apply
as the array that you pass as the second argument should be used as an argument list andcall
treat it as just one argument. -
The second function generates a currency function that can only be called once, since each invoked
curring
instance modifies the captured arrayargs
that was initialized when calledcurry
.For example:
-
addOne = curry(add)(1);
definesaddOne
with its ownargs
, initialized before[1]
-
addOne(2)(3)(4)
returns10
and changesargs
to[1, 2, 3, 4]
-
addOne(2)(3)(4)
(second time) fails withaddOne(...) is not a function
,
likeaddOne(2)
trying to calladd(1, 2, 3, 4, 2)
-
source to share