Currying in Javascript


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.
- If we pass a function with arguments : (a, b, c)
- 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 likefn(1, 2, 3)
. - Now ehat if we have less arguments like :
curriedFnAdd(1)(2)(3)
orcurriedFnAdd(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 intoif
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