In JavaScript Currying is a technique to translate a function which takes multiple arguments into a sequence of functions which takes single argument yet producing the same result.
Why do we need it?
- In functional programming, it provides a way of managing arguments to a function. Helps you deal with only one argument at a time.
- It decorates your code by reducing the number of arguments supplied to a function directly.
How does it look?
Notice that instead of returning the sum of a
and b
we return an anonymous function which takes b
as an argument. This gets immediately invoked upon return when we do sum(1)(2)
.
One has to ask a big question here. How does the scope of variable a
available to the inner anonymous function that gets invoked later 🤯?
The answer is very simple, its JavaScript Closures. If you haven't read my previous post about closures, please do.
Perpetual Curry
You can make the above curry technique by infinitely returning a function which takes one argument and accumulate the result till you say its enough. Something like,
sum(1)...(n)() //Output: Sum of n numbers
Let's get to the crux,
Writing a perpetual curry function is kind of writing a recursive function. The only difference is that for every recursion, our function will return another function. The above function perpetualCurry
will always return an anonymous function that can be invoked  immediately. This is how a basic infinite curry is constructed.
Let's make the above perpetualCurry
function a bit more useful that does our sum()
. Something like,
sum = (x, y) => x + y;
perpetualCurry(sum)(1)(2)(3)(4)(5)(); //Output: 15
Notice how we end the infinite curry, and notice how the first invocation takes a function as an argument.
But before our function gets too complex to understand let do one more stage of problem break down. Let's accumulate all our arguments and return it as an array. Also, try and end the infinite loop and return accumulated arguments.
See how we added another layer of function called curryWrapper()
. Notice on our recursion code how we use spread operator and accumulate our arguments. The first invocation is reserved for passing the sum()
function that can be used with call
or apply
to return our desired result.
Let's do our final perpetualCurry()
function that will return our desired result.
The only new addition to the function is the reduce
code block with fn.call
. The reduce()
just accumulates your result by executing our sum.call()
by passing two arguments at a time to that function. Finally the reduce()
returns the result of all addition when it reaches the end of args
array.
If you would like to read more about reduce
and call
I have added their MDN links at the bottom.
One of the most popular libraries written with this technique is, https://ramdajs.com/
Voila! we reached to the end of this post.
Ideas to further improve
- Accommodate more varied data types like inputting other functions, arrays, objects instead of just numbers.
- Curry async/await or Promise methods.
- Or a combination of all of the above.
Summary
- Curry technique can make your code clean and reduce complexity for functional programming as it deals with one argument at a time.
- You can extend currying by infinitely returning a curried function.
- You can reduce the number of line of code on your project by making the perpetual curry function take any datatype as argument.