Technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument is known as Currying. It means transformation of functions that translates a function from callable as f(x, y, z) into callable as f(x)(y)(z).
function curryMain(f) { // curryMain(f) does the currying transform
return function(x) {
return function(y) {
return f(x, y);
};
};
}
// usage
function sum(x, y) {
return x + y;
}
let curriedSum = curryMain(sum);
alert( curriedSum(1)(2) ); // 3
Implementation is straightforward: it’s just two wrappers.
- The result of curryMain(func) is a wrapper function(x).
- When it is called like curriedSum(1), the argument is stored in the Lexical Environment, and a new wrapper is returned function(y).
- After that this wrapper is called with “2” as an argument, and it passes the call to the original sum.
Some more advanced implementations of currying, such as _.curry from lodash library, return a wrapper that allows a function to be called both partially and normally:
function sum(x, y) {
return x + y;
}
let curriedSum = _.curry(sum); // using _.curry from lodash
library
alert( curriedSum(1, 2) ); // 3, still callable normally
alert( curriedSum(1)(2) ); // 3, called partially
Why is Currying used?
To understand the benefits we need a real-life example.
Suppose we have the logging function log(date, importance, message) that formats and outputs the information. In real life projects such functions may have a lot useful features like sending logs over the network, here we’ll just use alert:
function log(date, importance, message) {
alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}
Let’s curry it!
log = _.curry(log);
After that log works normally:
log(new Date(), "DEBUG", "some debug"); // log(a, b, c)
But also works in the curried form:
log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)
We can now easily make a convenience function for current logs:
let logNow = log(new Date());
// use it
logNow("INFO", "message"); // [HH:mm] INFO message
The logNow is log with a fixed first argument, in other words “partial” or “partially applied function” for short.
We can even go further and make such convenience function for current debug logs:
let debugNow = logNow("DEBUG");
debugNow("message"); // [HH:mm] DEBUG message
So:
1. Here we didn’t lose anything after currying: log is still callable normally.
2. We can very easily generate partial functions such as for today’s logs.





