When to use currying in JavaScript?

Apr 21, 2023#javascript#how-to

Currying is a technique of working with functions that transforms a function with multiple arguments into a series of functions that each take only one argument. For example, a function that takes three arguments f(a, b, c) can be curried into f(a)(b)(c). Currying does not call the function, it just transforms it.

Currying can be useful for several reasons:

  • It helps you avoid passing the same variable multiple times.
  • It divides your function into smaller functions that can handle one responsibility. This makes your function pure and less prone to errors and side effects.
  • It is used in functional programming to create higher-order functions.
  • It makes your code more readable and expressive.

You can use currying in JavaScript when you want to create partial functions that can be reused with different arguments. For example, if you have a function that logs a message with a date and importance level, you can curry it and create a partial function that logs messages for today with a fixed importance level:

// using _.curry from lodash library
function log(date, importance, message) {
  console.log(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}

let curriedLog = _.curry(log);

// create a partial function for today's logs
let logToday = curriedLog(new Date());

// use it
logToday("INFO", "message"); // [HH:mm] INFO message

// create another partial function for today's debug logs
let debugToday = logToday("DEBUG");

// use it
debugToday("message"); // [HH:mm] DEBUG message

Here an example to create a curry a function with three arguments:

// a function that calculates the volume of a cuboid
function volume(length, width, height) {
  return length * width * height;
}

// a currying function that takes a function and returns a curried version
function curry(func) {
  // return a function that takes the first argument
  return function (a) {
    // return another function that takes the second argument
    return function (b) {
      // return another function that takes the third argument
      return function (c) {
        // call the original function with all three arguments
        return func(a, b, c);
      };
    };
  };
}

// create a curried version of volume
let curriedVolume = curry(volume);

// use it to create a partial function for cubes
let cubeVolume = curriedVolume(10)(10);

// use it to calculate the volume of different cubes
console.log(cubeVolume(10)); // 1000
console.log(cubeVolume(20)); // 2000
console.log(cubeVolume(30)); // 3000

The currying function takes a function as an argument and returns a new function that takes the first argument of the original function. This new function returns another function that takes the second argument of the original function. This process continues until all the arguments of the original function are taken. Then, the original function is called with all the arguments and the result is returned.

For example, when we call curriedVolume(10)(10)(10), this is what happens:

  • The currying function takes volume as an argument and returns a new function that takes 10 as an argument.
  • This new function returns another function that takes 10 as an argument.
  • This another function returns another function that takes 10 as an argument.
  • This another function calls volume with 10, 10, and 10 as arguments and returns the result, which is 1000.

As you can see, currying allows you to create more specific and convenient functions from a general one.