Currying has become an essential part of modern JavaScript programming and is widely used in libraries and frameworks such as React, Redux, and Ramda. Currying is a functional programming technique that is widely used in JavaScript to create reusable functions.
In JavaScript, currying is achieved through closures, which allow for the creation of functions that retain access to their parent scope. By understanding currying, developers can write more concise, maintainable, and expressive code that is better suited to solving complex problems.
What is currying in Javascript?
Currying is a function that takes one argument at a time and returns a new function expecting the next argument. It’s a transformation of functions that translates a function from callable as f(a,b,c) into callable as f(a)(b)(c). In other words, currying is a functional programming technique that involves transforming a function that takes multiple arguments into a series of functions that each take a single argument.
To implement currying in JavaScript, we can create a function that takes the first argument of the original function and returns a new function that takes the second argument, and so on until all arguments have been consumed. Each returned function takes one argument and returns either another function (if there are more arguments to be consumed) or the result of applying the original function to all of the arguments.
Non-Curry | Curry |
const multiply = (a, b) => { return a * b; }; console.log(multiply(2, 3)); | const multiply = (num1)=> { return (num2) => { return num1 * num2; } }; console.log(multiply(2)(3)); // here is a modern way of implementing currying using the ES6 arrow function. It helps you write less code: const multiply = (num1) => (num2) => num1*num2; console.log(multiply(2)(3)); |
Why do we use currying in Javascript?
There are several benefits to using currying in JavaScript:
- Reusability: Currying allows you to reuse functions with different arguments. By creating a curried function that takes one argument at a time, you can easily create new functions that reuse the original function with different arguments.
- Partial application: Currying also allows you to partially apply a function with some of its arguments. This means that you can create a new function with some arguments already passed in, and then call that new function with the remaining arguments when needed.
- Composition: Currying is a powerful tool for function composition. By breaking down a function into smaller, curried functions, you can create new functions by combining these smaller functions in different ways. This can make your code more modular and easier to understand.
- Code clarity: Currying can make your code more readable and easier to reason about. By breaking down a function into smaller, simpler functions, you can create code that is easier to understand and maintain.
Example 1: Here’s an example of how partial application can be beneficial in JavaScript:
Let’s say you have a function called calculateTotal
that takes three arguments: subtotal
, taxRate
, and discount
. This function calculates the total price of an item after applying tax and discount:
function calculateTotal(subtotal, taxRate, discount) {
const taxAmount = subtotal * taxRate;
const discountedAmount = subtotal * discount;
const total = subtotal + taxAmount - discountedAmount;
return total;
}
Now, let’s say you have a scenario where you need to calculate the total price for multiple items, but the tax rate is the same for all items. In this case, you can use partial application to create a new function that takes only two arguments: subtotal and discount, and automatically passes in the tax rate:
const TAX_RATE = 0.1; // assume a 10% tax rate
const calculateTotalWithTax = (subtotal, discount) => calculateTotal(subtotal, TAX_RATE, discount);
// now you can use the new function to calculate the total for multiple items
const item1Total = calculateTotalWithTax(100, 0.2); // subtotal = 100, discount = 0.2
const item2Total = calculateTotalWithTax(50, 0.1); // subtotal = 50, discount = 0.1
Example 2: Here’s an example of how currying can facilitate function composition:
Let’s say you have two functions: double
and add
:
function double(num) {
return num * 2;
}
function add(a, b) {
return a + b;
}
Now, let’s say you want to create a new function that doubles the sum of two numbers. You can achieve this by composing the double
and add
functions using currying:
const doubleSum = (a, b) => double(add(a, b));
// now you can use the new function to double the sum of two numbers
const result = doubleSum(3, 5); // returns 16 (doubles the sum of 3 and 5)
In this example, we’ve used currying to compose the double
and add
functions into a new function doubleSum
that doubles the sum of two numbers. By breaking down the original functions into smaller, curried functions, we were able to create a new function that performs a complex calculation in a more modular and readable way.