The hardest part of currying is trying to define what it is in simple terms. It is easy to understand after you see some examples, but we unfortunately have to try and define it first.
Let’s try and define it as simple as possible first…
Currying is the process of creating a copy of a function but with a fixed parameter.
Not precise enough, let’s try again in more detail…
Currying is when you have a function with multiple arguments, or you have a function with arguments which returns another function with arguments, and then you create a new function that calls the main function with a parameter that is bound to the first argument of the main function.
Let’s be more exact…
The goal of currying is to get a function with multiple arguments down to one function with one parameter through the process of copying and binding.
If you copy and bind but still some arguments remain that is called a partial application, not technically currying.
It is MOST important to understand how hugely important a tool currying is in functional programming.
It is about creating an abstract function, from which you can create more specific functions without having to repeatedly write the main function throughout the program. This will make your code cleaner, more efficient, and more readable, which is the goal of functional programming.
We will take a look at how to curry functions using .bind() and using closures, and then throw in a unique functional programming example.
Currying Using .bind()
Let’s start with a normal function…
let add = (a, b) => a + b;add(1, 2); // 3
Before we move on, a little background on the .bind() function. For the purpose of currying we will make ‘this’ the first parameter of .bind(). That is because .bind() makes its first passed in argument the value of ‘this’ in the called function. That is irrelevant when we use .bind() for currying purposes, we just need a placeholder, which we will call ‘this’ because that is the accepted standard. Let’s move on.
The second parameter is the important part to understand. It will become fixed as the first argument of the called function, which is how we ‘curry’ the add function from above into a new function. Like this…
let add2 = add.bind(this, 2);
let add5 = add.bind(this, 5);add2(10); // prints 12
add5(10); // prints 15
Currying Using Closures
That is actually what currying literally is. It is breaking down functions with many arguments into more specific functions that each have only one argument. So instead of using the ‘add’ function from the above example, we will create this…
let add = a => b => a + b;let addTwo = add(2);addTwo(10); // prints 12
Don’t forget that when an internal function is returned, it gets its own execution context which includes the closure created by the outer function. That closure contains all variables and arguments of the outer function.
Evaluating the Above Code
The ‘add’ variable returns a function definition a => b => a + b;
When the addTwo variable is evaluated the JS Engine sees add(2) to the right of the equal sign, which is a function call so it creates a new function execution context.
It dives into that execution context and looks for variables and arguments. It sees ‘a’ is an argument, it checks the value, sees it is 2 and stores it. It sees the next line is to return a function so it stores ‘a’ with a value of 2 in a closure and gives it to the returned function for it to use later. It then garbage collects its arguments and variables.
The returned function definition, along with its closure containing ‘a’ with a value of 2, is now stored as the value of the variable addTwo.
addTwo = b => a + b; // its closure has... a = 2
JS Engine moves on. It sees … addTwo(6) … it looks for what addTwo is, sees the function definition that is being called, and thus creates a new execution context.
It dives in, sees an argument of ‘b’ and a value passed for it of 6. It stores that and looks to evaluate the expression of a + b.
It looks for the value of ‘a’, finds it in the function’s closure, then looks for the value of ‘b’, which was passed in, it adds those values and returns the result.
The key thing to remember about all this is that the closure gets stored in the returned function’s execution context at the time it was created.
We can then create another curried function, based off the original function…
let addTen = add(10);addTen(6); // prints 16
You can now understand what will happen with this function. It will store the addTen as…. b => a + b; …., but this time the closure will have stored ‘a’ with a value of 10.
Functional Programming and Currying
Here is an example of how to create a curried function to fetch data from two different lists of objects. One is a list of NBA players, another is a list of MLB players. This is closer to what you might see in the wild.
let nbaPlayers = [
team: 'Golden State Warriors',
name: 'Seth Curry',
team: 'Golden State Warriors',
name: 'Kevin Durant',
team: 'Cleveland Cavaliers',
name: 'Lebron James',
team: 'Chicago Bulls',
name: 'Michael Jordan',
let mlbPlayers = [
team: 'Chicago Cubs',
name: 'Anthony Rizzo',
team: 'Chicago Cubs',
name: 'Kris Bryant',
team: 'St. Louis Cardinals',
name: 'Mark McGwire',
So you could do this…
let basketballPlayers = nbaPlayers.map(player => player.name);
let baseballPlayers = mlbPlayers.map(player => player.name);
Or you can create a curried function in order to not repeat yourself…
const get = property => object => object[property];const getPlayers = get('name');let basketballPlayers = nbaPlayers.map(getPlayers);
let baseballPlayers = mlbPlayers.map(getPlayers);
The ‘get’ function above will take in any property and return a function. That function takes in an object as its argument and returns the given property in the object.
We then set ‘getPlayers’ to get(‘name’). Then we get all players from each sport by mapping over each array with the getPlayers as the callback. So instead of having to repeat the function, we only write it once and call it twice.
We can take this a step further by creating a new first class function.
let getActivePlayers = player => player.status === 'active';let activeBasketballPlayers = nbaPlayers.filter(getActivePlayers);
let activeBaseballPlayers = mlbPlayers.filter(getActivePlayers);
And bringing it all together, we can chain some functions...
let activeNBAplayers = nbaPlayers.filter(getActivePlayers).map(getPlayers);let activeMLBplayers = mlbPlayers.filter(getActivePlayers).map(getPlayers);
You may want to learn about first class functions here.
Currying in Frameworks