From Clueless to Currying in Five Minutes

Sharad Satsangi
6 min readApr 20, 2021

In the past month I’ve grasped and forgot the finer points of currying functions a few times, so here’s a quick article that will cover the concept generally.

Before we get into it, know that currying is used a lot in functional programming, and it relies on the concept of higher order functions, i.e. passing one function to another. If that sounds confusing, check out the quick read about that concept I wrote here. It’s a 3 minute read to get you up to speed.

While the act of currying functions gets its name from Haskell Curry, it helped me to think about it like making a curry. Traditionally, when you call a function, you pass all its arguments in at once, and what the function returns your result. When you curry a function, the function is split into partial functions and it takes its arguments one at a time, passing the first argument to the first partial function. When the first partial returns, the curried function will take the next argument, and so on, until there are no more arguments to process. Add an argument and let it simmer. When it’s ready, add the next argument. It’s a lot like cooking a curry.

Okay, that’s a lot to unpack there. Don’t Panic. It’s a simple concept and in a few minutes you’ll have the hang of it, too. Check out the coding examples below.

This guy made a mean Recursive Aloo Gobi

So let’s look at this madlibs function, written traditionally, below.

let madlibs = (name, food, number) => 
'My name is ' + name +
' and I love ' + food +
', I could eat ' + number +' plates of it!'

All the arguments grouped together in the parentheses. Calling this function in our code by passing all our arguments in at once, like this:

console.log (madlibs("Jerry","Spaghetti","10"))

And our function puts this on the console:

My name is Jerry and I love Spaghetti, I could eat 10 plates of it!

To currymadlibs, we re-write it like so:

let madlibs = 
name =>
food =>
number =>
'My name is ' + name +
' and I love ' + food +
', I could eat ' + number +' plates of it!'

Notice the nested arrow functions, splitting up our arguments. Which changes the way we call it:

console.log (madlibs("Jerry")("Spaghetti")("10"))

… now each argument is separate, and each is passed one at a time to each partial function, but we get the same output.

My name is Jerry and I love Spaghetti, I could eat 10 plates of it!

However, we don’t need to call it all at once! If we do this:

console.log (madlibs("Jerry")("Spaghetti"))

The console will log the final arrow function. Depending on your environment, you may only see [function] logged to your console, but what’s being returned is:

(number) => 'My name is ' + name + ' and I love ' + food + ', I could eat ' + number + ' plates of it!'

If you try running the code over at playcode, you can see this logged in the console.

The important thing to note here is how currying gives us the ability to slowly add our arguments to our function. While it may not be apparent why just yet, the fact we can pass arguments in gradually and come back to our function later with more arguments is useful, we’ll come back to this concept shortly.

But before we do that, one more thing you need to know is that we can use a number of functional programming libraries to have JavaScript curry a traditional function for us, for example, lodash:

import _ from 'lodash'let madlibs = (name, food, number) =>
'My name is ' + name +
' and I love ' + food +
', I could eat ' + number +' plates of it!'
madlibs = _.curry(madlibs)let jerry = madlibs("Jerry")let jerrysFavoriteFood = jerry("Spaghetti")console.log (jerrysFavoriteFood('10'))

Here, we use the _ function from lodash to curry the traditional version of madlibs and then we call the first partial and assign the returning function to the variable jerry in the line

let jerry = madlibs("Jerry")

… and similarly, we call the second partial using jerry("Spaghetti") and assign the last partial function to jerrysFavoriteFood so when we call the final function, we still get our output:

My name is Jerry and I love Spaghetti, I could eat 10 plates of it!

This last example is similar to the ways I employed lodash while working through a Redux tutorial online. Let’s say I have a dataset of users and I’m looking for the users who love the color red:

let users = [
{id: 1, username: "cambot", favorite_color: "red"},
{id: 2, username: "gypsy", favorite_color: "purple"},
{id: 3, username: "tom", favorite_color: "red"},
{id: 4, username: "crow", favorite_color: "gold"},
{id: 5, username: "joel", favorite_color: "red"},
{id: 6, username: "mike", favorite_color: "blue"},
{id: 7, username: "jonah", favorite_color: "yellow"}
]
let faveColor = (favorite_color, obj) => obj.favorite_color === favorite_colorlet usersThatLoveRed = users.filter(x => faveColor('red', x))console.log(usersThatLoveRed)

… which will log the following data.

[
{id:1,username:"cambot",favorite_color:"red"},{id:3,username:"tom",favorite_color:"red"},{id:5,username:"joel",favorite_color:"red"}
]

(The format it will be logged out as may be less pretty depending on your environment.)

This works, but look at the way we call faveColor. We pass it 2 arguments, 'red’ and x. Using currying, we can make the code more readable. In the example below, we achieve the same output:

import _ from 'lodash'let users = [
{id: 1, username: "cambot", favorite_color: "red"},
{id: 2, username: "gypsy", favorite_color: "purple"},
{id: 3, username: "tom", favorite_color: "red"},
{id: 4, username: "crow", favorite_color: "gold"},
{id: 5, username: "joel", favorite_color: "red"},
{id: 6, username: "mike", favorite_color: "blue"},
{id: 7, username: "jonah", favorite_color: "yellow"}
]
let faveColor = _.curry((favorite_color, obj) => obj.favorite_color === favorite_color)let usersThatLoveRed = users.filter(faveColor('red'))console.log(usersThatLoveRed)

The above implementation does the same thing, however note that now when we call users.filter on faveColor we are only passing one argument, since we are only concerned with the first partial function. In a large codebase with a lot of moving parts, this method of employing currying can make the code more readable for everyone. It’s great for making code self-documenting, too.

And really, that’s what currying functions is all about

  • Either by hand or by using a functional library like lodash, we take a function that takes multiple arguments and split it up into partial functions that take single arguments
  • The partials we call return the partials yet to be executed. We _can_ call all of those functions in one call, or just the partials we need to use.

It’s the potential to only call the first few partials that I think makes currying such a great tool. If we only need some of the curried partials, we stand to make our code easier to read and have less we need to keep track of in our code.

Catch ya next time!

--

--