Understanding JavaScript currying

Understanding JavaScript currying

Originally posted on dev.

Currying is a concept from lambda calculus, but don’t let that freak you out — it’s quite simple to implement.

Currying is a function that takes one argument at a time and returns a new function expecting the next argument. It is a transformation of functions that translates a function from callable as f(a, b, c) into callable as f(a)(b)(c).

In this article, we’re going to explore what currying is in Javascript, why and where you should use currying, and how to implement it with code examples.

What is currying in JavaScript?

Currying simply means evaluating functions with multiple arguments and decomposing them into a sequence of functions with a single argument.

In other terms, currying is when a function — instead of taking all arguments at one time — takes the first one and returns a new function, which takes the second one and returns a new function, which takes the third one, etc. until all arguments are completed.

Why should I use currying?

There are several reasons why currying is ideal:

  • Currying is a checking method to make sure that you get everything you need before you proceed
  • It helps you to avoid passing the same variable again and again
  • It divides your function into multiple 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 a higher-order function
  • This could be personal preference, but I love that it makes my code readable

How does currying work?

Currying is a function that accepts multiple arguments. It will transform this function into a series of functions, where every little function will accept one argument:

Noncurried version//
const add = (a, b, c)=>{
return a+ b + c
}
console.log(add(2, 3, 5)) // 10

Curried version//
const addCurry =(a) => {
return (b)=>{
return (c)=>{
return a+b+c
}
}
}
console.log(addCurry(2)(3)(5)) // 10

Currying in Javascript may be a little bit tricky to understand in terms of its definition, but it will become clear as we implement it.

So, let’s dive into more code examples.

Example one: A simple, three-parameter function

First, I’m going to create a simple function that accepts three parameters:

const add =(a, b, c)=>{
return a+b+c
}
console.log(add(2, 3, 5)) // 10

After outputting this function, the result is 10.

What happened here is that this function is adding all the parameters of the numbers which we have passed.

Now, this first example is just a simple function that accepts multiple parameters.

How do I convert an existing function to a curried version?

Example two: Converting an existing function into a curried function

Let’s try this second example and see how we can implement the curry function.

In this example, this function is going to accept one argument and return a series of functions:

const addCurry =(a) => {
return (b)=>{
return (c)=>{
return a+b+c
}
}
}

This is the curry implementation of the function. If we output this, the result will be 10:

console.log(addCurry(2)(3)(5)) // 10

In the first example, we created a function addCurry that accepted three arguments ab, and c, added their sum a+b+c, (2)+(3)+(5), and returned the output as 10.

This second example showed how we implemented the same function but with a curried version that takes one argument a and returns a function that takes another argument b, which returns a function that takes another argument c, and that function returns their sum, which gave us the same output as example one: 10.

What we have done here is a nested function, so each of these functions takes one argument that returns another argument and the function doesn’t complete until it receives all parameters.

Example three: Creating a friend request curry function

In this example, we are going to create a simple curry function where a user sends a friend request to his friend John:

const sendRequest(greet){
return function(name){
return function(message){
return `${greet} ${name}, ${message}`
}
}
}
sendRequest('Hello')('John')('Please can you add me to your Linkedin network?')

Output:

"Hello John, Please can you add me to your Linkedin network?"

We created a function sendRequest that requires only one argument, greet, and it returns the name of the person and the message we want to send to the user. Then, when we invoked the function, it outputted the message.

Basic vs. advanced currying techniques

Basic currying

const getPanCakeIngredients = (ingredient1) =>{
return (ingredient2) => {
return (ingredient3) => {
return ${ingredient1}, ${ingredient2}, ${ingredient3}; } } } getPanCakeIngredients('Egg')('flour')('milk');

This code example is a basic way of implementing currying.

In the above example, we created a function getPanCakeIngredients that takes ingredient 1 as a single argument and returns a series of functions that contain the other ingredients we need to make the pancake.

The function isn’t complete until it receives all parameters, which means if the ingredients for the pancake are not complete, the function won’t return any good result.

Advanced currying

Here is a code example of advanced currying:

const curry =(fn) =>{
 return curried = (...args) => {
if (fn.length !== args.length){
return curried.bind(null, ...args)
}
return fn(...args);
};
}
const totalNum=(x,y,z) => {
return x+y+z 
} 
const curriedTotal = curry(totalNum);
console.log(curriedTotal(10) (20) (30));

In the example above, we created a function that requires a fixed number of parameters.

It receives a function curry as the outer function. This function is a wrapper function. It returns another function named curried, which receives an argument with the spread operator ( ...args), and it compares the function length fn length.

The function length means that whatever the number of parameters we pass here, it will reflect in the length property of the function.

But the argument will increase every time. If the number of the parameters we need is not equal, it is going to return curried. If we call bind, this creates a new function and we pass the ( ...args).

N.B., bind creates a new function.

Modern currying with ES6

As my bonus tip, here is a modern way of implementing currying using the ES6 arrow function. It helps you write less code:

const sendRequest = greet => name => message =>
`${greet} ${name}, ${message}`
sendRequest('Hello')('John')('Please can you add me to your Linkedin network?')

Output:

"Hello John, Please can you add me to your Linkedin network?"

Currying vs. partial application

Now that you know how currying works, what is the difference between currying and a partial application? This is one question programmers keep asking.

I finally have the answer to this question. But before I dive deeper into this explanation with some code examples, it would be best if we familiarize ourselves with their definitions.

  • Currying: a function that accepts multiple arguments. It will transform this function into a series of functions, where every little function will accept a single argument until all arguments are completed
  • Partial application: a function is partially applied when it is given fewer arguments than it expects and returns a new function expecting the remaining arguments

Knowing the definitions aren’t enough for us to understand their differences. You’ve seen currying in action, but this is an example of partial application:

const addPartial=(x,y,z) => {
return x+y+z 
}
var partialFunc= addPartial.bind(this,2,3);
partialFunc(5); //returns 10

What we did here isn’t a curried version, but we did a partial application of the addPartial function. We created a simple function that adds a list of numbers and returns their output.

N.B., a function is called a partial application when some of the argument it passes is incomplete.

Currying and partial application are not really different; they are related, but they have different theories and applications.

The partial application converts a function to another function, but with smaller arity.

Conclusion

For developers, currying can feel complicated. While it is tricky to understand, you will learn it better when you implement it in your JavaScript projects.

I have implemented currying in some of my projects and learned by practice. These are some things I have used currying for:

  • Currying can be used to manipulate the DOM in Javascript
  • It can be used to trigger event listeners
  • Currying can be used when you want to create a function that will receive only single arguments

Source: dev