If you are an intermediate or advanced JavaScript developer, you’ve probably come across this term. Javascript function currying is a technique where a function with multiple arguments is transformed into a sequence of functions, each with a single argument. It’s a popular technique amongst developers who like functional programming. So let’s explore what it is, and why you would use it.

How to curry a function

Let’s consider the following function that is used to calculate simple interest over a period of time:

// Using the simple interest equation
// P is the initial balance
// R is the annual interest rate
// T is the time in years
function simpleInterest(P, R, T) {
  return (P * R * T) / 100;
}

// Calculate the simple interest of $1000 with an annual interest rate of 5% for 10 years
console.log(simpleInterest(1000, 5, 10)); // Outputs: 500

In order to curry the simpleInterest() function, we need to break it down into 3 functions, each taking only 1 argument. This will look like the following:

function simpleInterest(P) {
  return function(R) {
    return function(T) {
      return (P * R * T) / 100;
    };
  };
}

// We can then use the call all functions in a row giving them the respective arguments
console.log(simpleInterest(1000)(5)(10)); // Outputs: 500

In both examples, we calculated the simple interest of an initial amount of $1000 for 10 years with an annual interest rate of 5%, which would add up to $500.

The Benefits of Javascript Function Currying

Code Reusability and Modularity

Function currying encourages you to focus on modularity and code reusability. Instead of creating new functions that accept multiple arguments, we can create new functions that accept fewer arguments and make use of other existing functions in the code.

Let’s say we have a function that takes the radius r of a circle and returns its area.

function circleArea(r) {
	return π * (r ** 2);
}

console.log(circleArea(5)) // Outputs: 78.53982...

Now we want to create a function that calculates the volume of a cylinder which depends on the radius r and the height h. We can either create a new function that accepts both parameters, or we can use function currying to reuse the circleArea() function.

function circleArea(r) {
	return π * (r ** 2);
}

function cylinderVolume(r, h) {
	return π * (r ** 2) * h;
}

console.log(cylinderVolume(5, 10)); // Outputs: 785.39816... 

function curriedCylinderVolume(r) {
	return function(h) {
    return circleArea(r) * h;
  };
}

console.log(curriedCylinderVolume(5)(10)); // Outputs: 785.39816... 

The function cylinderVolume() takes 2 arguments and repeats some of the functionality that circleArea() does. But the function curriedCylinderVolume() accepts only 1 argument and makes use of the circleArea() function that already exists.

This is a very simple example of how currying encourages modularity code reusability. However, the same concept can be applied to more complex functions to make them simpler, more decoupled, and more readable.

Flexibility in Function Composition

Function composition is a technique where several functions are put in sequence such that the output of one becomes the input of the next. To learn more, you can check out this amazing article about function composition.

Curried functions return other functions, allowing you to compose complex functions with simple, reusable pieces. This flexibility makes your code more readable and easier to reason about.

Simplified Parameter Management

With currying, you don’t have to pass all parameters at once; you can pass them one at a time. This becomes handy when you don’t have all the arguments at the same time in the sequence of your business logic. Also, it’s very useful when you want to create more specialized functions based on general ones.

Practical Examples of Function Currying

Let’s explore some more practical examples of function currying in JavaScript.

Example 1: Partial Application

The concept of partial application, where you fix a number of arguments and create a new function, is a common use case for currying.

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

const multiplyByTwo = multiply.bind(this, 2);

console.log(multiplyByTwo(5)); // Outputs: 10

In the example above, multiplyByTwo() is a new function derived from the multiply() function, with the first argument set to 2.

Example 2: Creating Specialized Functions

You can create specialized functions from more general functions using currying.

function greet(greeting, name) {
	return `${greeting}, ${name}!`;
}

const greetHello = greet.bind(this, 'Hello');

console.log(greetHello('World')); // Outputs: Hello, World!

In this example, greetHello() is a new function derived from the greet() function, with the greeting set to ‘Hello’.

Example 3: Event Handling

We can also use currying to handle events. You can create a general event handler function and derive specialized functions for specific events.

function eventHandler(type, event) {
	console.log(`Event type: ${type}, Event value: ${event.target.value}`);
}

const keyPressHandler = eventHandler.bind(this, 'KeyPress');

// Attach keyPressHandler to an input field

In the above example, you can use keyPressHandler() as a specialized handler for the ‘KeyPress’ events.

Closure vs Currying in JavaScript

Some people get confused about the difference between function currying and closures. These are 2 overlapping concepts in Javascript, but they are not the same. A closure is a function that has access to its own scope, the outer function’s scope, and the global scope. On the other hand, currying is a technique of breaking down a function that takes multiple arguments into a series of functions that take one argument at a time.

So looking at our first example:

function simpleInterest(P) { // <- Main function. It has access to the 'P' parameter only.
  return function(R) { // <- A closure. It has access to 'P' and 'R'.
    return function(T) { // <- Another closure. It has access to 'P', 'R', and 'T'.
      return (P * R * T) / 100;
    };
  };
}

We can see that closures are used to implement function currying. But closures are also used for many other use cases in Javascript like callback functions, emulating private methods, creating function factories, and more. So function currying and closures are closely related, but they are not the same thing.

Final Notes

Function currying is a powerful tool in a JavaScript developer’s arsenal. It can significantly enhance the reusability, readability, and maintainability of your code. It might not seem very straightforward at first glance. But as you read and write more code throughout your career, you’ll start to appreciate the beauty of Javascript function currying.

Similar Posts