Understanding Currying in JavaScript
Currying is a powerful concept in functional programming, where a function is transformed into a series of functions that each take a single argument. In this article, we’ll explore how currying works and how you can use it in JavaScript.
What is Currying?
Currying is a technique in functional programming where a function that takes multiple arguments is transformed into a series of functions, each taking one argument. It helps in creating more modular, reusable, and flexible code by allowing functions to be applied step by step.
For example:- Normal Function: f(a, b, c)
- Curried Function: f(a)(b)(c)
Why Use Currying?
- Partial Application: Currying allows you to set some parameters of a function upfront and pass the remaining parameters later.
- Cleaner Code: By breaking down a function into smaller functions, currying leads to more readable and modular code.
- Reusability: Curried functions can be reused in different contexts with different arguments.
How Does Currying Work?
Let's look at an example to understand how currying works in JavaScript.
Example of Curryingfunction multiply(a) {
return function(b) {
return a * b;
}
}
const multiplyBy2 = multiply(2); // Partial application
console.log(multiplyBy2(5)); // Output: 10
console.log(multiplyBy2(10)); // Output: 20
In the example above, the `multiply` function takes one argument `a` and returns another function that takes the second argument `b`. By calling `multiply(2)`, we create a function `multiplyBy2` that is a partially applied version of the original function. We can then call `multiplyBy2(5)` to multiply 2 and 5. And we are reusing multiplyBy2 function again.
Chaining Multiple Functions
Currying allows you to chain multiple functions together by applying arguments one by one. This enables more dynamic and flexible use cases.
function sum(a) {
return function(b) {
return function(c) {
return a + b + c;
}
}
}
console.log(sum(1)(2)(3)); // Output: 6In this example, the `sum` function is curried to take three arguments. You can apply each argument one at a time and the final result is returned when all arguments are applied.
Infinite Currying
Infinite currying allows you to chain an arbitrary number of function calls. Instead of returning a final value immediately, each function in the chain returns another function, allowing you to keep calling the function indefinitely until a certain condition is met (like passing a specific argument to terminate the chain).
function infiniteSum(a) {
return function (b) {
if (b === undefined) {
return a; // Stops the chain when no argument is passed
}
return infiniteSum(a+b)
// Recursive call the function
}
}
console.log(infiniteSum(1)(2)(3)(4)(5)()); // Output: 15The code demonstrates infinite currying where each function call accumulates a sum, and the recursion stops when no argument is passed, returning the total sum.
Infinite currying is useful for scenarios where you might not know how many arguments will be passed, such as in dynamic user input or progressive calculation functions.
Real-life Example of Currying
Currying is often used in scenarios where we need to break down a complex process into smaller, more manageable steps. One real-life example is a system that applies discounts to a shopping cart in a store. Instead of applying all discounts at once, we can apply each discount step-by-step in a curried function.
function applyDiscount(price) {
return function (discount) {
price -= price * (discount / 100); // Apply the discount to the price
return function (extraDiscount) {
if (extraDiscount) {
price -= price * (extraDiscount / 100); // Apply another discount if provided
}
return price; // Return the final price
}
}
}
console.log(applyDiscount(100)(10)(5)); // Output: 85 (Apply 10% and 5% discounts)In this example, the `applyDiscount` function is curried to apply multiple discounts to a product. Each discount is applied step-by-step, and the final price is returned after all discounts are applied.
Here's how it works:
- First Call: The function is called with the price (e.g., `100`). It returns another function to apply the first discount.
- Subsequent Calls: The returned function accepts discount values (e.g., `10`, `5`) and applies them to the price.
- Final Calculation: After all discounts have been applied, the final price is returned.
Currying is helpful in scenarios like this, where we need to apply several steps sequentially but want to maintain flexibility in how we handle each step.
Benefits of Currying
- Code Reusability: By using currying, you can reuse functions with different arguments, reducing code duplication.
- Function Composition: Currying allows functions to be composed together in a modular way, enhancing the overall functionality of the code.
- Partial Application: Currying makes it easier to work with partially applied functions, where you can pass some arguments ahead of time.