1

function sum(a){
    if(!a) return 0;
    return b=>a + sum(b);
}


console.log(sum(2)(3)); // returns a string "ab=&gta + sum(b)"
console.log(sum(2)(3)()); // says sum (..)(..) is not a function

Is there a particular reason this is happening?

VLAZ
  • 26,331
  • 9
  • 49
  • 67
malikite
  • 44
  • 5

3 Answers3

6

When you write:

console.log(sum(2)(3));

this can be re-written to be:

const fn = sum(2);
console.log(fn(3));

If you look at what sum(2) returns, it will return another function:

return b=>a + sum(b);

You then invoke this function using fn(3), you perform:

2 + sum(3)

When you call sum(3), you again return the same above function, so you are doing:

2 + function

Since addition doesn't work between a number and a function, JS will try and convert the function to a primitive by calling .valueOf() on your function. Calling .valueOf() on a function will return it's string version, hence making 2 + function perform concatenation between your function and the number 2, giving you:

2b=>a + sum(b)

Your second attempt of sum(2)(3)() tries to invoke this string, and so you get an error when you try and treat the string as something callable.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • Hmm interesting, but shouldn't it be such that the sum function is pushed onto the call stack until some termination condition and the final return value be sent back as the return value for the function i.e sum(3) ? – malikite Jan 18 '21 at 05:33
  • I've just realized that the function is non-terminating :S – malikite Jan 18 '21 at 05:38
  • 1
    @malikite what happens is that you invoke the first time (outside of your function), this pushes sum onto the call stack, it then returns a function, this pops `sum()` off the call stack. When you invoke the returned function, it does another call to `sum`, which pushes it onto the call stack. Again, sum returns the a function to where it was invoked thus popping it off the call stack. This results in `() => a + sum(b)` turning into `() => a + () => sum(b)`, the function that is returned isn't invoked, so `sum` is no longer called or added to the call stack, but rather converted to a string. – Nick Parsons Jan 18 '21 at 06:42
0

You don't need sum(b) in the return statement, just b

function sum(a){
    if(!a) return 0;
    return b=>a + b;
}


console.log(sum(2)(3)); 

If you want indefinite chaining of curried functions, see this question: Variadic curried sum function

yunzen
  • 32,854
  • 11
  • 73
  • 106
  • 1
    I think the idea is for an infinitely curried function where the terminal condition is passing a falsy value. So you'd be able to do `sum(2)(3)(4)(5)()` if you wish. – VLAZ Jan 12 '21 at 10:33
-1

Maybe try this:

function sum(a, b){
    if(!a) return 0;
    if(!b) return a;
    return a + b;
}

console.log(sum(2,3));