Currying is a technique in functional programming where a function is transformed into a sequence of functions, each taking a single argument. In JavaScript, currying is achieved by transforming a function that takes multiple arguments into a chain of functions, each taking a single argument and returning a function that takes the next argument until all arguments have been passed.
Benefits of Currying
Increased Reusability - By breaking down a function into smaller, single-argument functions, you can reuse the same code in different ways.
Improved Code Readability - Currying makes your code more readable by breaking down complex operations into smaller, more manageable chunks.
Improved Code Composition - Currying makes it easier to combine functions into more complex operations, as it allows you to build up functions incrementally.
How to Curry a Function in JavaScript
To curry a function in JavaScript, you'll need to write a function that returns a function. Here's a simple example:
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
};
}
};
}
In this example, the curry
function takes a fn
as its argument and returns a curried
function. The curried
function takes any number of arguments and stores them in an args
array. If the length of args
is equal to or greater than the length of fn
, it calls fn
with apply
and passes args
as its argument. If the length of args
is less than the length of fn
, it returns a new function that takes args2
and concatenates it with args
before calling curried
with apply
.
Use Cases
Simple Addition
const add = curry((a, b) => a + b);
const add10 = add(10);
console.log(add10(5)); // 15
console.log(add10(20)); // 30
In this example, add
is a curried function that takes two arguments, a
and b
, and returns their sum. add10
is a new function that has been created by calling add
with 10
as its argument. When add10
is called with 5
, it returns 15
, and when it's called with 20
, it returns 30
.
Simple Multiplication
Here's a simple example of how to curry a function that multiplies two numbers:
const multiply = curry((a, b) => a * b);
const double = multiply(2);
console.log(double(5)); // 10
console.log(double(20)); // 40
In this example, multiply
is a curried function that takes two arguments, a
and b
, and returns their product. double
is a new function that has been created by calling multiply
with 2
as its argument. When double
is called with 5
, it returns 10
, and when it's called with 20
, it returns 40
.
Advanced Function Composition
Currying also allows for advanced function composition, where multiple functions can be combined and reused in different ways. Here's an example:
const compose = (f, g) => x => f(g(x));
const add = curry((a, b) => a + b);
const multiply = curry((a, b) => a * b);
const add10 = add(10);
const double = multiply(2);
const addAndDouble = compose(double, add10);
console.log(addAndDouble(5)); // 30
const doubleAndAdd = compose(add10, double);
console.log(doubleAndAdd(5)); // 20
In this example, the compose
function takes two functions f
and g
and returns a new function that takes an argument x
and returns the result of calling f
with the result of calling g
with x
. The add
and multiply
functions are curried functions as described in the previous examples. The add10
and double
functions are new functions created by calling add
and multiply
with their respective arguments.
The addAndDouble
function is created by calling compose
with double
as the first argument and add10
as the second argument. When addAndDouble
is called with 5
, it returns 30
, which is the result of adding 10
to 5
and then doubling the result.
The doubleAndAdd
function is created by calling compose
with add10
as the first argument and double
as the second argument. When doubleAndAdd
is called with 5
, it returns 20
, which is the result of doubling 5
and then adding 10
to the result.
Conclusion
Currying is a powerful technique in functional programming that allows you to break down complex operations into smaller, more manageable chunks. By transforming a function that takes multiple arguments into a chain of functions, each taking a single argument, you can increase code reusability, improve code readability, and make it easier to compose functions into more complex operations. With the understanding of how to curry a function in JavaScript and some examples of its usage, you can start incorporating this technique into your own code and experience the benefits it provides.