How to quickly understand currying in JavaScript

In this article I’ll quickly introduce you to currying, it’s purpose, and show you how to understand it with plain and simple code.

Ivan Korolenko
The Startup
3 min readJun 21, 2020

--

What is currying?

Currying is the process of converting a function of multiple arguments to a chain of functions of one argument. Like so:

const createUser = (firstName, lastName) => 
`${firstName} ${lastName}`
// becomes
const createUser = (firstName) => (lastName) =>
`${firstName} ${lastName}`

But it’s not comfortable to do those manipulations manually every time we need to break down our functions througn currying. So we make curry function that can do it for us.

Why do we need this?

Curried functions are easy to partially apply, and therefore easy to reuse in slightly different scenarios. Imagine we need to create a user like in the example above. Ok, that’s easy, we already made a function for it. But now let’s make it more real.

const createUser = (role, firstName, lastName, login, passwordHash) => *some logic goes here*

Cool, we can create users. But what if we want to create a manager user in several places of our app? We can just call createUser(“manager”, …) every time. But what if that name will need to be changed later for technical reasons? Say, we’ll need to merge our database with a database of some other company, and they use numbers for roles? Search for every call to createUser and replace the first argument? Seems kinda wrong.

So we foresaw that scenario and made this function:

const createManagerUser = (firstName, lastName, login, passwordHash) => createUser("manager", firstName, lastName, login, passwordHash)

Feels wrong again, right? Redundant and verbose, because we duplicate our arguments for no reason. Imagine if we’ll need more arguments or something like createManagerUserWithCompanyAvatar(). We’ll need to copy those arguments all other every time.

DRY principle is not happy with us!

How do we fix this? Easy! We curry our basic function (createUser) and partially apply it when we need to create something more specific from it (createManagerUser)!

const createManagerUser = curry(createUser)("manager")

Clean, beautiful, easy.

This code will work the same way as the verbose one. And we don’t even need to change the original function, we just make a curried version of it.

How to create this magic?

I’ve spent some time looking for simple and already made example of a curry function that can accept any number of arguments, so we don’t need to pass the amount of arguments every time like

curry(addTwoNumbers, 2)
curry(addThreeNumbers, 3)

But alas haven’t been able to find one that reads like a plain English text and gives clean perspective on that’s going on. So I wrote one myself.

const curry = (fn) =>     
function curried(...args) {
const haveEnoughArgs = args.length >= fn.length
const partiallyApplied = (...moreArgs) =>
curried(...args.concat(moreArgs))

if (haveEnoughArgs) return fn(...args)
return partiallyApplied
}

What it does:

  • Creates a new function, called curried. Arguments of that new function are transformed into an array for ease of manipulation
  • Determines if we have enough arguments to run given function. Simply substracting the quantity of passed arguments array from quantity of given function’s arguments
  • Creates partially applied version of given function in case we don’t have enough arguments to run it right now. Arguments of that function are transformed into array, added to already passed arguments and passed to the next recursive call of a curried function.
  • Now final decision. If we have enough arguments, we just call given function with them. If we don’t, we return a partially applied function. When called, it will take us to first step until we have enough arguments.

Looks logical and simple.

Can I use it in my project?

Of course, here’s the npm package!

You can also fork/clone it from GitHub and use it like a regular script.

You can find instructions in both npm and GitHub.

That’s all!

I hope, this journey was interesting. If you want to continue it, here you can read about different types of currying in JavaScript.

If you have any questions, feel free to leave a comment here or contact me through my website (link in my Medium profile -> “How to contact me?”). I’ll be happy to help you.

Thank you for reading!

--

--