DEV Community

Rahul Vijayvergiya
Rahul Vijayvergiya

Posted on

JavaScript Currying

Currying is a powerful concept in functional programming that transforms a function with multiple arguments into a sequence of functions, each taking a single argument. This technique allows for more modular and reusable code. In JavaScript, currying can be implemented in various ways. This blog will explore currying, provide examples, and discuss different methods to achieve n argument currying.

What is Currying?

Currying is the process of converting a function that takes multiple arguments into a series of functions that each take a single argument. For example, a function f(a, b, c) can be transformed into f(a)(b)(c).

Why Use Currying?

  • Partial Application: Currying allows you to fix some arguments of a function and create a new function.
  • Higher-Order Functions: It facilitates the use of higher-order functions, which take other functions as arguments or return them.
  • Code Reusability: Curried functions are more reusable and composable.
  • Functional Composition: Currying enables better functional composition, where complex functions are built by combining simpler functions, leading to cleaner and more maintainable code.

Simple Currying Example

Let's start with a basic example to understand how currying works.

Uncurried Function

Here's a simple function that adds three numbers:

function add(a, b, c) {
  return a + b + c;
}

console.log(add(1, 2, 3)); // Output: 6

Enter fullscreen mode Exit fullscreen mode

Explanation: This function add takes three arguments a, b, and c, and returns their sum. When we call add(1, 2, 3), it returns 6.


Curried Function

Now, let's convert this function into a curried version:

function curryAdd(a) {
  return function(b) {
    return function(c) {
      return a + b + c;
    };
  };
}

console.log(curryAdd(1)(2)(3)); // Output: 6
Enter fullscreen mode Exit fullscreen mode

Explanation: The curryAdd function takes an argument a and returns a function that takes an argument b, which in turn returns a function that takes an argument c. The final function returns the sum of a, b, and c. When we call curryAdd(1)(2)(3), it sequentially passes the arguments 1, 2, and 3 through the nested functions, resulting in 6.

Currying with Arrow Functions

JavaScript's arrow functions provide a concise way to create curried functions.

const curryAddArrow = a => b => c => a + b + c;

console.log(curryAddArrow(1)(2)(3)); // Output: 6

Enter fullscreen mode Exit fullscreen mode

Explanation: The curryAddArrow function is an arrow function that takes an argument a and returns another arrow function that takes b, which returns yet another arrow function that takes c. The final arrow function returns the sum of a, b, and c. When we call curryAddArrow(1)(2)(3), it sequentially passes the arguments 1, 2, and 3 through the nested arrow functions, resulting in 6.


Use Case

1.Configuration Functions

A common use case for currying is configuration functions. For instance, imagine you are creating a logging utility where you want to configure the logging level and the message format separately.

function logger(level) {
  return function (message) {
    console.log(`[${level}] ${message}`);
  };
}

const infoLogger = logger('INFO');
const errorLogger = logger('ERROR');

infoLogger('This is an info message');
errorLogger('This is an error message');

Enter fullscreen mode Exit fullscreen mode

2. String Formatter

Let's consider a practical example where currying can be used to create a string formatter. This formatter will allow you to configure the prefix and suffix separately.

function formatter(prefix) {
  return function (suffix) {
    return function (str) {
      return `${prefix}${str}${suffix}`;
    };
  };
}

const htmlFormatter = formatter('<b>')('</b>');
console.log(htmlFormatter('Hello')); // <b>Hello</b>

const parensFormatter = formatter('(')(')');
console.log(parensFormatter('123')); // (123)

Enter fullscreen mode Exit fullscreen mode

Currying in Modern JavaScript Libraries

Currying is commonly used in modern JavaScript libraries like Lodash and Ramda. For example, in Lodash, you can use the _.curry method to create curried functions easily.

const _ = require('lodash');

function multiply(a, b, c) {
  return a * b * c;
}

const curriedMultiply = _.curry(multiply);

console.log(curriedMultiply(2)(3)(4)); // 24
console.log(curriedMultiply(2, 3)(4)); // 24

Enter fullscreen mode Exit fullscreen mode

Currying with N Arguments

Let go through below example of currying with a recursive function that adds n arguments. We'll use currying to create a function that can accept any number of arguments, one at a time, and add them together.

function curryAddition(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn(...args);
    } else {
      return function(...nextArgs) {
        return curried(...args, ...nextArgs);
      };
    }
  };
}

// This function sums an array of numbers
function add(...nums) {
  return nums.reduce((acc, num) => acc + num, 0);
}

// Creating a curried version of the addition function
const curriedAdd = curryAddition(add);

// Function to handle n arguments
function curriedAddN(...initialArgs) {
  function adder(...args) {
    if (args.length === 0) {
      return curriedAdd(...initialArgs);
    }
    initialArgs.push(...args);
    return adder;
  }
  return adder;
}

// Examples
const addFiveNumbers = curriedAddN();
console.log(addFiveNumbers(1)(2)(3)(4)(5)()); // 15

const addThreeNumbers = curriedAddN(1)(2)(3);
console.log(addThreeNumbers()); // 6

const addNumbersInSteps = curriedAddN(1, 2)(3)(4, 5);
console.log(addNumbersInSteps()); // 15

Enter fullscreen mode Exit fullscreen mode

Conclusion

Currying is a powerful technique in functional programming that enhances modularity and reusability of code. By transforming functions into chains of single-argument functions, currying allows for partial application and flexible function composition. Whether for configuration, string formatting, or complex computations, currying can make your code more expressive and adaptable.

Top comments (0)