Currying is a functional programming technique that allows you to transform a function with multiple arguments into a sequence of functions that each take a single argument.
1function add(a, b, c) {
2 return a + b + c;
3}
4
5function curriedAdd(a) {
6 return function (b) {
7 return function (c) {
8 return a + b + c;
9 };
10 };
11}
12
13add(1, 2, 3); // 6
14curriedAdd(1)(2)(3); // 6
You need to understand closures and higher-order functions to understand currying. You can learn more about closures in the following article:
1function curriedAdd(a) {
2 return function (b) {
3 return function (c) {
4 return a + b + c;
5 };
6 };
7}
8
9const baseValue = curriedAdd(100);
10const baseValueWithGST = baseValue(10);
11const baseValueWithGSTAndServiceTax = baseValueWithGST(5);
12
13console.log(baseValueWithGSTAndServiceTax); // 115
14
We can reuse baseValue
, baseValueWithGst
and baseValueWithGstAndServiceTax
in various parts of our code.
Currying allows for lazy evaluation. This means that a function does not evaluate, until all its arguments are received.
You can create a curried function that can take a variable number of arguments. This is called dynamic currying.
1const add = args => args.reduce((a, b) => a + b, 0);
2
3const addItems = (...args) => {
4 return (...newArgs) => {
5 if (newArgs.length === 0) return add(args);
6 return addItems(...args, ...newArgs);
7 };
8};
9
10const base = addItems(100);
11const discount = base(-10);
12const tips = discount(5);
13const tax = tips(8);
14tax(); // 103
Here, addItems
is a higher-order function that returns a curried version of the original function.
1// higher order function takes in a variable number of arguments
2const addItems = (...args) => {
3 // returns a function that also takes in a variable number of arguments
4 return (...newArgs) => {
5 if (newArgs.length === 0) return add(args);
6 return addItems(...args, ...newArgs);
7 };
8};
The inner function returns the higher-order function again after merging the higher-order function arguments with the inner function arguments.
1// for example, base = addItems(100), discount = base(-10)
2// args = [100], newArgs = [-10]
3return addItems(...args, ...newArgs);
Finally when we call addItems
without any arguments, we execute the original function, with all the arguments.
1// for example, tax()
2// args = [100, -10, 5, 8], newArgs = []
3if (newArgs.length === 0) return add(args);
Fancy word, simple concept. Partial application is when you fix a few arguments of a function and generate a new function that takes the remaining arguments in a curried fashion.
1const largePizza = 720;
2const sparklingWater = 120;
3const salad = 200;
4const tax = 160;
5
6// partial application curry
7const base = addItems(largePizza, sparklingWater, salad)(tax);
8base(); // 1200
Currying is a powerful technique that can help you create functions that are more reusable, readable, and flexible. It can also help you write more concise and expressive code.