How can I create a function in javascript return like this:
sum(1,2) //3
sum(1,3)(2) // 6
I have tried with this code but it wrong?
function(a,b) {
return (c) {
return a + b + c;
}
}
How can I create a function in javascript return like this:
sum(1,2) //3
sum(1,3)(2) // 6
I have tried with this code but it wrong?
function(a,b) {
return (c) {
return a + b + c;
}
}
You could override the valueOf
of the inner function and sum the arguments (reference)
function sum(...a) {
function inner(...b) {
a.push(...b)
return inner;
}
inner.valueOf = () => a.reduce((c, d) => c + d, 0)
return inner
}
console.log( +sum(1, 2) )
console.log( +sum(1, 3)(2) )
console.log( +sum(1, 2, 3)(4, 5)(6) )
You could use rest syntax to collect all the parameters and return a function. This needs another ()
at the end to terminate the recursion
const sum = (...a) => (...b) => b.length
? sum(...a, ...b)
: a.reduce((c, d) => c + d, 0)
const sum = (...a) => (...b) => b.length
? sum(...a, ...b)
: a.reduce((c, d) => c + d, 0)
console.log( sum(1,2)() )
console.log( sum(1,3)(2)() )
console.log( sum(1,2,3)(4,5)(6)() )
Since you are not going for fixed length arguments, I can only think of using a hack like below where we finally still return a function (summer
) but modify the valueOf()
for the inner function summer
so that in the end when we do an operation like *1
on the last returned function which will be summer
only, summer.valueOf()
get's invoked and we can see the total sum till now.
function sum(...args){
function summer (...args2){
let argsArr = [...args,...args2];
return sum(...argsArr)
}
summer.valueOf=()=>args.reduce((acc,curr)=>acc+=curr,0);
return summer;
}
console.log(sum(1,2)*1);
console.log(sum(1,2)(3)*1);
console.log(sum(1,2)(3)(4,5,6,7,8)(9,10,11)*1);
The result of a function cannot vary based on whether it is called again or not. So, it is not possible to have sum(1, 2)
that returns a number in one case but a function if called as sum(1, 2)(3)
.
However, since functions are objects in JavaScript, you can have the function return a new function with a property that has the total:
const sum = (function calculate() {
return function running(...xs) {
const total = xs.reduce((sum, x) => sum + x, running.total ?? 0);
return Object.assign( calculate(), { total } )
}
})();
console.log( sum(1, 2).total );
console.log( sum(1, 3)(2).total );
console.log( sum(1, 2, 3)(4, 5)(6).total );
console.log( sum(1, 2, 3, 4, 5, 6).total );
console.log( sum(1)(2)(3)(4)(5)(6).total );
const x = sum(1, 2);
console.log( x(3).total );
console.log( x(3).total );
This uses a self-referencing IIFE to keep things clean, as there is no need for an extra function. However, it is otherwise equivalent to:
function calculate() {
return function running(...xs) {
const total = xs.reduce((sum, x) => sum + x, running.total ?? 0);
return Object.assign( calculate(), { total } )
}
}
const sum = calculate();
The calculate()
function always returns a new running()
function that keeps track of the total and itself returns a new running()
function with the total
attribute. When running()
calculates the sum, it uses the total
it has or a zero if no total
was present (first time calculate
was executed).
sum(1, 2, 3) (4, 5) (6) .total --> 21
^^^^^^^^^^^^ ^^^^^^ ^^^
| | |
total = 6 <--+ | |
total = 6 + 9 <-----+ |
total = 15 + 6 <---------+
If you prefer, you can also make sure that the function is convertible to a primitive number by overriding the valueOf
and @@toPrimitive
methods. Technically, you do not need both but does not hurt to be more thorough:
const sum = (function calculate() {
return function running(...xs) {
const total = xs.reduce((sum, x) => sum + x, running.total ?? 0);
return Object.assign( calculate(), {
total,
valueOf: () => total,
[Symbol.toPrimitive]: () => total,
})
}
})();
const sum = (function calculate() {
return function running(...xs) {
const total = xs.reduce((sum, x) => sum + x, running.total ?? 0);
return Object.assign( calculate(), {
total,
valueOf: () => total,
[Symbol.toPrimitive]: () => total,
})
}
})();
console.log( +sum(1, 2) );
console.log( +sum(1, 3)(2) );
console.log( +sum(1, 2, 3)(4, 5)(6) );
console.log( +sum(1, 2, 3, 4, 5, 6) );
console.log( +sum(1)(2)(3)(4)(5)(6) );
const x = sum(1, 2);
console.log( +x(3) );
console.log( +x(3) );
console.log( sum(1, 2) + sum(3) + sum(4)(5) );
Follow the below code :-
function currying(first, ...other){
var argmnts = [first, ...other];
return function interalCurrying(first, ...other) {
if(first){
argmnts = [...argmnts , first, ...other];
return interalCurrying;
} else {
return argmnts.reduce((acc , val)=>{
return acc+val;
},0);
}
}
}
console.log(currying(2,3)(4)());
console.log(currying(2)(3)(4)());