Home > Posts > Currying in Javascript

Currying in Javascript

Mohit Ranjan
Mohit Ranjan
Cover Image for Currying in Javascript
Mohit Ranjan
Mohit Ranjan

Function Currying

While preparing for interviews, all of us have stumbled across this word currying and have been wondered about its usage or need. Let me break it down for you, Its a way based on Javascript's functional programming, that helps us to make a function reusable by using its partial logic. Sounds confusing? here's an example.

const add = (a, b) => {
    return a+b
}

A simple function to add two numbers right? What happens if we wanted to create a function that adds 7 to the numbers we pass. Would we create anew function like this :

const add7 = (a) => {
    return 7+a
}

We could but we developers are lazy (and smart), using the concept of bind that we learnt above we could do this instead:

const add7 = add.bind(null, 7)

Isn't this the same as we bound Naruto's message function with a new object and a custom message of our own? So here instead of creating a brand new defination, we just copied add and bund it with a new this which was null and 7.

Wait, but what does currying have to do with this? Well, currying is even better and readable way of creating add7 function. Lets moify our add function first.

const add = (a) => {
    return (b) => {
        return a + b
    }
}

Now if we want to call add, we do it like this:

add(5)(7)

And, if we have to create any other function like add7

const add7 = add(7)

add7(5) // 12

Looks a lot cleaner isn't it? This is the whole purpose of currying method. It makes our code a lot cleaner when we are trying to re-use a part of some function. Only catch is that we have to define the function in one way.

Well, we have a solution to this as well. We can create a Higher Order Function to convert a simple function into a curried one using what we just learnt. Not only this, lets make a function as such :

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

const curriedFnAdd = curry(Add)

//curried function above handles all the cases below

curriedFnAdd(1)(2)(3) //6
curriedFnAdd(1, 2)(3) //6
curriedFnAdd(1)(2, 3) //6
curriedFnAdd(1, 2, 3) //6

Here is a function that handles all of it.

function curry(fn) {
  return function curried(...args) { // Receives Number of args as params
    if (args.length >= fn.length) { // fn.length returns the number of arguments in that function.
      return fn.apply(null, args);
    } else {
      return function (...newArgs) {
        return curried.apply(null, args.concat(newArgs));
      };
    }
  };
}

Let me explain the code above before you freak out.

  1. If we pass a function with arguments : (a, b, c)
  2. for case of curriedFnAdd(1, 2, 3) or more, we will just return the function itself, bound with its own arguments. At this point its just a normal function call, just like fn(1, 2, 3).
  3. Now ehat if we have less arguments like : curriedFnAdd(1)(2)(3) or curriedFnAdd(1, 2)(3) (lesser arguments than the original functions). In this case we will need recursion because we don't know how many arguments are going to be there (there could be one or two or more…). In any case we are just going to return the applied function with adding (concatenating) argument from each call. similar to this : f(1)(2)(3) => f(1, 2)(3) => f(1, 2, 3) finally it stops since it gets into if condition.

This all might sound confusing in first read, but implementation and re-visits will help you a lot.

After understanding the concept you can try a really popular interview question :

Write a curried function that returns sum from two to infinite numbers : 

f(1)(2)(3) // 6
f(1)(2)(3)(4) // 10
... so on