Deep Dive Into Javascript Currying Function From Basic To Advance

Let's start this article by understanding what the heck is Currying in JavaScript and What are the real world use cases.
Currying is the concept of transforming a function with multiple arguments into a sequence of functions, each taking one or multiple arguments of the original function. This process transforms a function with multiple arguments into a sequence of nesting functions. Each returned function expects the next subsequent argument.
For example any function passed as curried function will be transformed from callable as func(a, b, c) into callable as func(a)(b)(c).
// This is 2-arity (arguments) function
function normalFunc(a, b) {
//...
}
// This is 3-arity (arguments) function
function normalFunc(a, b, c) {
//...
}
Let's understand basic Curry function with example:
const sum = (a, b) => a + b;
sum(1,2) // 3
Function sum takes 2 arguments and return summation of value of these arguments. Now if we break these arguments in curried version:
const sum =(a)=> {
return (b) => {
return a + b;
}
}
console.log(sum(1)(2)) // 3
So here we have turned sum(1,2 ) to multiple function calls sum(1)(2).
At this point, if we try to decouple function and arguments then, this can be easily achievable by using curried expression.
function simpleCurry(func) {
return function(a){
return function(b) {
return func(a, b);
};
};
};
OR with ES6
const simpleCurry = (func) => (a) => (b) => func(a,b)
const sum = (a, b) => a + b;
const multiply = (a, b) => a * b;
console.log(simpleCurry(sum)(1)(2)); //3
console.log(simpleCurry(multiply)(4)(2)); // 8
Let's move to the indefinite arguments which can be achieved by using recursive approach:
Till now, we have seen how to convert a normal function to curried function. Let’s create a function that multiply n number of parameters by using arguments property of the function.
function multiply() {
let args = [...arguments];
console.log(args);
return args.reduce((arg, val) => arg * val, 1);
}
console.log(multiply(2, 3)); // 6
console.log(multiply(2, 3, 6)); // 36
Here, we are assigning the value of arguments to args using the spread operator. Next, reduce function, compute product of args return.
The problem here is, it solves problem of evaluating arity (arguments received) which are part of first function call but do not return function which would be taking care of next level of arity.
Let’s write a code that will return a function n number of times which will in turn create a recursion.
function multiply(...args1) {
return function multplyCallback(...args2){
return multiply(...args1, ...args2);
}
}
console.log(multiply(1)(2)(3));
// ƒ multplyCallback(...args2){
// return multiply(...args1, ...args2);
// }
Here, this function will work for any number of curried arguments. But as you can check in the console, the final value is still not what we expected. It will always be a returned function and that's not what we want. So we do a little tweak here, in each loop:
- We have to return a function
curryingReturnthat will have reference toinfiniteMultiCurryingfunction (recursion). - Before returning
curryingReturn, we compute the product of the values in the argument list. - We store the product as a property of the
curryingReturnfunction. - Now
curryingReturncan be called as a normal function, which will in turn callinfiniteMultiCurryingfunction or we can print the value via its valueOf property
Let's see the modified code:
function infiniteMultiCurrying(...args1) {
function curryingReturn(...args2) {
return infiniteMultiCurrying(...args1, ...args2);
}
curryingReturn.valueOf = args1.reduce((acc, item) => (acc *= item), 1);
return curryingReturn;
}
console.log(infiniteMultiCurrying(1)(2)(3)(4)(5).valueOf); // 120
console.log(infiniteMultiCurrying(1)(2)(3)(4)(5)(6).valueOf); // 720
console.log(infiniteMultiCurrying(1)(2)(3)(4)(5)(6)(7).valueOf); // 5040
Here, we are creating a new member variable called valueOf for curryingReturn function and assigning it the computed total value.
This creates confusion but if we understand basic object property, a function can also have properties in it.
function nameFunc() {
//...
}
nameFunc.newProperty = "Javascript";
console.log(nameFunc.newProperty) // Javascript
I hope this helped to set up basic understanding of Currying concept or idea of using the Currying function! Thanks for reading!!

