Hero image

Currying


Currying is a trick in programming where you provide a function with only some of its expected arguments. You then return another function that expects the rest of the arguments, where it will then run the original function with all of them combined.

If you do not provide all the required arguments to a function it is called Partial Application as you have partially applied the arguments to your function, and will need to supply the rest later.

Syntax

To curry a function, all you need to do is return a function variable that will then execute the code with all the supplied arguments. A good example is a greeting message where you can change the greeting word and the users name.

JS
Typescript

In this case we hard coded that the greet function must first be called with the greeting and then the sayX functions needed to be called with the name. The note at the end is valid, but does look a bit funny. Lets see if we can fix it up.

How to automatically curry

Lets say with our greet function we want give developers an option to both use currying and not - ie. with both the following syntax:

  1. greet("Hello", "Tim")
  2. const hello = greet("Hello"); hello("Tim");

Turns out in javascript this is possible! We can do this because functions actually tell you how many parameters they expect! All you need to do is use the length key of a function. Knowing this you can automatically fire your function once the length is reached.

JS
Typescript

Above is a template for what we will use to set up auto currying. We have a function to call to wrap ours, and then a function we can recursively call until we want to execute it, which is yet to be filled in.

So what are the things we need to think about with our recursive function? There are a few things I want it to do:

  1. Automatically execute the function when the required number of parameters is reached.
  2. Allow early execution by passing in no parameters.

Lets start with the first task - executing the original function if the number of parameters is reached:

JS
Typescript

And that is all we need to do, but there is a lot happening here so lets look at a few tests.

JS
Typescript

So what happened here? Lets go through the tests to see what got called.

I will go through the stack, indenting where the call stack has been added to or we enter a new indent in the code.

Note: The examples have the same initial setup with the wrapping function, so I will show it once here.

JS
Typescript

curriedAdd(1,2,3)

The first test provided all three parameters at the same time. Here is the story of what happened.

JS
Typescript

curriedAdd(1,2)

The second test provided only two of the required 3 parameters and in the end returned a new function rather than the added result. Here is the story.

JS
Typescript

Allowing early execution

So our first goal is complete. We can pass our parameters in order and can pass as few or as many as we like. The next step is to allow execution of our function at any point by passing in zero parameters. Before looking below have a think about how this might be achieved. It is done through a simple if statement somewhere.

JS
Typescript

The full code

Below is the full code brought together with each part we walked though. 25 lines of code including all the comments. Not too bad.


If you have never used it before - codeclip.io is an interactive tool where you can step through the code! Try using the step options below to see outputs.

NOTE - If you just see a blank square above you likely have 3rd party cookies disabled. You can see the same thing here.



What to read more? Check out more posts below!