function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) return fn.apply(this, args);
return (...more) => curried.apply(this, [...args, ...more]);
};
}
const add = curry((a, b, c) => a + b + c);
add(1)(2)(3); // 6
add(1, 2)(3); // 6
Currying turns a function that takes several arguments into a chain of functions that each take one argument. For example, add(a, b, c) becomes add(a)(b)(c).
In practice, JavaScript curry helpers are more flexible. They accept any number of arguments per call. They run the original function once enough arguments have been collected. So add(1, 2)(3) also works.
Why it is useful:
- You can build specific functions from general ones. Example:
const logError = log('error'). - You can combine small functions in point-free style. This means writing functions without naming their arguments, like
items.map(double)instead ofitems.map(x => double(x)).
Currying is close to partial application, which fixes some arguments at once. bind does partial application.
How the code works: it compares the number of collected arguments with fn.length, the number of declared parameters. When there are enough, it calls fn. Otherwise it returns a function that collects more.
Limitation: this does not work with rest parameters or default values, because length does not count them.
- Currying turns
f(a, b, c)intof(a)(b)(c). - It is built on closures that collect arguments.
- It uses
fn.lengthto know when to call the original function. - It is related to partial application, which
binddoes. - It lets you build reusable, specific functions from general ones.
- Currying (https://javascript.info/currying-partials)javascript.info