Reputation: 66560
I have function that look 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's how the function should look like and should work as:
function add(a, b, c, d) {
return a+b+c+d;
}
curry(add, 1, 2)(3, 4);
but Wikipedia Article says that
it can be called as a chain of functions, each with a single 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 be used as this:
function add(a, b, c, d) {
return a+b+c+d;
}
curry(add)(1)(2)(3)(4);
Am I right?
Upvotes: 1
Views: 1085
Reputation: 3401
Strictly speaking, currying converts a function with many arguments into a series of functions each with one single argument, as in your second curry
function:
If you call all of them (in chain), you get the full application of the function, which produces the same result as the original function:
curry(add)(1)(2)(3)(4)
returns the same as add(1, 2, 3, 4)
, i.e.10
If you call only a subset, you get a partially applied function:
addOne = curry(add)(1);
addOneAndTwo = addOne(2);
addOneAndTwo(3)(4)
returns 10
In Javascript, currying is usually used as a synonym for partial application, as in your first curry
function. Paraphrasing Prototype documentation:
curry curries (burns in) arguments to a function, returning a new function that when called with call the original passing in the curried arguments (along with any new ones).
For more detailed explanations, see What is the difference between currying and partial application.
Here is a working implementation of a true curry function in javascript by Evan Borden.
A few caveats:
In your first function, fn.call
is wrong. You must use fn.apply
, as the array that you pass as the second argument must be used as a list of arguments and call
treats it as only one argument.
Your second function generates a curried function that can be called only 1 time, as each called curring
instance modify the captured args
array, which was initialized when curry
was called.
For example:
addOne = curry(add)(1);
defines addOne
with its own args
initialized to [1]
addOne(2)(3)(4)
returns 10
and modify args
to [1, 2, 3, 4]
addOne(2)(3)(4)
(a second time) fails with addOne(...) is not a function
,
as addOne(2)
tries to call add(1, 2, 3, 4, 2)
Upvotes: 2