Currying is a functional programming technique that transforms a function with multiple arguments into a sequence of functions, each taking their own argument(s), allowing for more flexible and reusable code.
For instance, rather than invoking a function in the usual manner:calculateArea(length, width);
A curried version would be structured as:calculateArea(length)(width);
The Advantages
Ok but why is it beneficial? Let’s create a function to multiply two numbers.
function multiply(a, b) {
return a * b;
}
console.log(multiply(2, 5)); // Output: 10Now lets refactor with currying:
const multiply = (a) => (b) => a * b;
const double = multiply(2); // Partially apply the first argument
console.log(double(5)); // Output: 10
console.log(double(8)); // Output: 16What’s Improved?
Reusability: The
doublefunction is created by partially applying the argument2. Now, you can reuse it anywhere to double a number without repeating logic.Modularity: By splitting the function into smaller steps, it’s easier to manage and debug.
Another example? Say we have this logger function.
function logger(fileName, logLevel, message) {
console.log(`[${fileName}] [${logLevel}] ${message}`);
}
logger("app.js", "INFO", "Application started");
logger("app.js", "ERROR", "Unhandled exception");With currying:
const logger = (fileName) => (logLevel) => (message) =>
console.log(`[${fileName}] [${logLevel}] ${message}`);
// Create specialised loggers
const appLogger = logger("app.js");
const infoLogger = appLogger("INFO");
const errorLogger = appLogger("ERROR");
// Use them
infoLogger("Application started"); // Output: [app.js] [INFO] Application started
errorLogger("Unhandled exception"); // Output: [app.js] [ERROR] Unhandled exceptionWhat’s Improved?
Consistency: The
fileNameis fixed at the beginning, ensuring all logs from the same file follow a uniform format.Avoid Repetition: By partially applying arguments (
appLoggerandinfoLogger), you don’t need to repeatedly pass the samefileNameandlogLevel.Flexibility: You can create multiple specialised loggers for different contexts and reuse them, simplifying the codebase.
You’re not limited to using this technique in Javascript either. Here’s a PHP example:
function multiply($a, $b) {
return $a * $b;
}
echo multiply(2, 5); // Output: 10With currying:
function multiply($a) {
return function ($b) use ($a) {
return $a * $b;
};
}
$double = multiply(2); // Partially apply the first argument
echo $double(5); // Output: 10
echo $double(8); // Output: 16By leveraging closures, we can create a powerful chain of functions where each function remembers the context in which it was created.
This approach allows us to break a function into smaller, reusable pieces and defer execution until all arguments are provided.
The Grumpy Dev is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.
