Currying in JavaScript
Currying is an important concept that is at the heart of any functional programing language. So let's have a look at what it is and why to use it.
What is currying?
Currying is the mean to transform a function of arity n to n functions of arity 1. So, this is the theory. It simply means that currying allows you to not specify all arguments when you call a function. Let's take a simple example. You should be used to do something like this:
const add = (a, b) => a + b
add(1, 2) //should return 3
In a curryfied way, I should do something like this instead:
const add = a => b => a + b
add(1)(2) //should return 3
Did you notice how the add
function is built? It is a function that takes one argument and return another function that takes the second argument. Once all the arguments are there, the computation happens. So in this example, calling add(1)
returns a function.
Currying is possible in JavaScript because functions are first-class citizen. It means that functions are like any other values. They can be assigned to variables, passed as argument to other functions and returned by functions.
Why currying is important
Currying gives you the opportunity to partially configure a function and then, it is the mean to create reusable functions. Let's take another example. Suppose I have a collection like this:
const movies = [
{
"id": 1,
"name": "Matrix"
},
{
"id": 2,
"name": "Star Wars"
},
{
"id": 3,
"name": "The wolf of Wall Street"
}
]
Now, suppose I want to extract the ids of this collection. I could simply use the map
function to iterate over the collection:
movies.map((movie) => movie.id) //should return [ 1, 2, 3 ]
Great, but suppose I have a second collection of series:
const series = [
{
"id": 4,
"name": "South Park"
},
{
"id": 5,
"name": "The Simpsons"
},
{
"id": 6,
"name": "The Big Bang Theory"
}
]
And suppose I want to extract the ids as I did before with the movies:
series.map((serie) => serie.id) //should return [ 4, 5, 6 ]
The callbacks of map
are strictly the same, but we operated on two different collections. In this case, currying can be the solution. Let's make a function call get
that should extract a property from an object:
const get = property => object => object[property];
Now from this function I can create another function, called getId
that is just a partial configuration of the get
function:
const getId = get('id');
At this step, getId
is still a function and this is great because we are now able to use it inside our map calls:
movies.map(getId); //should return [ 1, 2, 3 ]
series.map(getId); //should return [ 4, 5, 6 ]
Isn't that nice? But we can go one step further. Suppose now, that we want to extract the name from our objects. How can you could achieve that? Just create a function called getName
derived from the get
function:
const getName = get('name');
And then, you can use it on your collections to extract the name:
movies.map(getName); //should return [ 'Matrix', 'Star Wars', 'The wolf of Wall Street' ]
Conclusion
Currying is an important part of a functional programing. I encourage you to play with it like I did in this article. If you use functional libraries like Ramda or Lodash/fp the most of functions are curryfied by default, which is great! So remember that decomposing functions of n arguments to n functions of 1 argument is not a really hard task with the ES6 syntax and the lamda functions! So you have no excuse not to create reusable code thanks to currying!
Hi,
function foo(x){
return function bar(y){
console.log(x + y);
return bar;
}
}
foo(1)(2)(3)(4)(5)(6);
Is it possible to find the sum of all parameter (1+2+3+4+5+6) = 21
Closure with recursion.
foo(1)(2)(3)(4)(5)(6)…nth;
var getID = (arr) => (id) => arr.map((obj)=> ob[id]);
We can also do above as :
var getID = (arr) => (id) => {
return arr.map(function(obj){
return obj[id];
}