Practical Examples of Currying in JavaScript
Full Stack Developer with hands-on experience of more than 1 year. Proficient in both Back-end and Front-end technologies, with a strong commitment to delivering high-quality code
Currying is a functional programming technique that transforms a multi-argument function into a sequence of single-argument functions, improving modularity and reusability.
In this blog, we explore 6 real-world examples of currying in JavaScript.
π For a deeper dive into the theory behind currying, check out our companion blog β Functional Programming in JavaScript: Partial Application and currying
Practical Examples of Currying
Below are practical examples demonstrating how currying can be applied in real-world JavaScript scenarios.
Example 1: Formatting Log Messages
Currying creates reusable logging functions for different log levels.
const formatLog = level => message => `[${level}] ${message}`;
const logError = formatLog('ERROR');
const logInfo = formatLog('INFO');
console.log(logError('Connection failed')); // [ERROR] Connection failed
console.log(logInfo('User logged in')); // [INFO] User logged in
Explanation: The formatLog function is curried to first accept a level, then a message, creating specialized functions like logError.
Example 2: Dynamic Discount Calculator
Currying simplifies creating functions for specific discount percentages.
const discount = percent => price => price * (1 - percent / 100);
const tenPercentOff = discount(10);
const twentyPercentOff = discount(20);
console.log(tenPercentOff(100)); // 90
console.log(twentyPercentOff(100)); // 80
Explanation: discount is curried to fix the percentage, creating reusable functions for specific discounts.
Example 3: DOM Manipulation
Currying streamlines DOM updates by pre-configuring element selectors.
const updateElemText = id => content => (document.querySelector(`#${id}`).textContent = content);
const updateHeaderText = updateElemText('header');
updateHeaderText('Hello World');
// HTML: <div><h1 id="header">Hello World</h1></div>
Explanation: The curried function specializes in updating a specific DOM elementβs text.
Example 4: Operation-Based Calculator
Create a curried function that performs different operations based on a parameter.
const calculate = operation => a => b => {
if (operation === 'sum') return a + b;
if (operation === 'multiply') return a * b;
if (operation === 'divide') return a / b;
if (operation === 'subtract') return a - b;
return 'Invalid Operation';
};
console.log(calculate('sum')(2)(4)); // 6
console.log(calculate('multiply')(2)(4)); // 8
Explanation: The function takes an operation type and two numbers, performing the specified operation in a curried manner.
Example 5: Infinite Argument Summation
Handle an arbitrary number of arguments using recursion.
const sum = a => b => b !== undefined ? sum(a + b) : a;
console.log(sum(1)(2)(3)()); // 6
console.log(sum(1)(2)(3)(4)()); // 10
Step-by-Step Explanation:
Define the Curried Function:
sumis defined as a curried function using arrow functions. It takes an initial argumentaand returns a function that expectsb.Check for
b: Ifbis provided (i.e., notundefined), the function returns a newsumfunction with the accumulated valuea + b. This enables recursive calls for more arguments.Base Case: When
bisundefined(e.g.,sum(1)(2)(3)()), the function returns the accumulated valuea.Execution Example:
sum(1)returns a function witha = 1, expectingb.sum(1)(2)computesa + b = 1 + 2 = 3, returns a newsumwitha = 3.sum(1)(2)(3)computesa + b = 3 + 3 = 6, returns a newsumwitha = 6.sum(1)(2)(3)()hasb = undefined, so it returnsa = 6.For
sum(1)(2)(3)(4)(), the process continues until()returns1 + 2 + 3 + 4 = 10.
Example 6: Generic Curry Function
Convert any function into a curried version.
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func(...args);
}
return (...next) => curried(...args, ...next);
};
}
const join = (a, b, c) => `${a}_${b}_${c}`;
const curriedJoin = curry(join);
console.log(curriedJoin(1, 2, 3)); // '1_2_3'
console.log(curriedJoin(1)(2, 3)); // '1_2_3'
console.log(curriedJoin(1, 2)(3)); // '1_2_3'
Step-by-Step Explanation:
Define the Curry Function: The
curryfunction takes a functionfuncand returns acurriedfunction that handles arguments.Check Argument Count:
currieduses the spread operator (...args) to collect arguments. If the number of arguments (args.length) is at least the number required byfunc(func.length), it callsfuncwith all arguments.Return New Function: If fewer arguments are provided,
curriedreturns a new function that collects additional arguments (...next) and combines them withargsfor the next call.Execution Example:
curriedJoin(1, 2, 3):args = [1, 2, 3],func.length = 3, sojoin(1, 2, 3)is called, returning'1_2_3'.curriedJoin(1):args = [1], fewer than 3, returns a function expecting more arguments.curriedJoin(1)(2, 3): Combinesargs = [1]withnext = [2, 3], callsjoin(1, 2, 3), returns'1_2_3'.curriedJoin(1, 2)(3): First call storesargs = [1, 2], second call adds3, callsjoin(1, 2, 3), returns'1_2_3'.
Thanks for checking out the blog! π
Tried out the examples? Let me know how it went or drop your favourite use case for currying in the comments!