0

In a recent interview, I was asked to write a function that adds numbers and accepts parameters like this:

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

But I am not able to solve below answer, how to get default as 0 in below output?

console.log(sum())
console.log(sum()())
Amit Sharma
  • 31
  • 1
  • 12
  • `sum(),()` I assume you mean `sum()()` – Keith Sep 12 '22 at 14:58
  • 1
    `console.log(sum(1)); console.log(sum(1)());` I'm not sure this is even possible. How can the result of `sum(1)` be _both_ a returned number, **and** a callable function? – Cerbrus Sep 12 '22 at 14:59
  • Yes it's sum()() – Amit Sharma Sep 12 '22 at 14:59
  • Might be possible by overriding the .toString method on the function to return the value when it's passed to console.log (as per example linked by Nina below) – phhu Sep 12 '22 at 15:12
  • 1
    @Cerbrus, it is possible, like [here](https://stackoverflow.com/questions/44347757/what-do-we-call-this-type-of-argument-passing-mul123-how-to-solve-this-and/44347813#44347813) – Nina Scholz Sep 12 '22 at 15:12
  • https://stackoverflow.com/questions/5832891/variadic-curried-sum-function @Cerbrus here is the link – Amit Sharma Sep 12 '22 at 15:16

3 Answers3

0

Well solution should be something like this:

const sum = (...args) => {
  const reducer = (acc, arg) => acc + arg;
  let total = args.reduce(reducer, 0)
  const add = (...args2) => {
    if (args2.length) {
      total = args2.reduce(reducer, total)
      return add
    }
    return total
  }

  add.toString = () => total;
  add.valueOf = () => total;

  return add
}



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

It seems that I cannot quiet find a function that needs to be overriden in order to get nice output.

So in case of console.log(sum()) you will get ƒ add(). But if you write like this console.log("" + sum()) you will get 0 in console. console.log is not calling toString automatically :( probably some other method needs to be overriden additionally.

Ivan Vasiljevic
  • 5,478
  • 2
  • 30
  • 35
  • In snippet everything will work correctly, in my browser console I had a problem with `toString` – Ivan Vasiljevic Sep 12 '22 at 15:48
  • unclear why your add function is returning total. It should be returning `add` – epascarello Sep 12 '22 at 15:50
  • Well when you call sum(1)(). add function is called without any params, so I need to handle that case. In that case, function needs to return current result from previous function call sum(1). I store that in total and in that case function is returning that result. If we don't do that sum(1)() will return undefined. – Ivan Vasiljevic Sep 12 '22 at 15:53
  • 2
    It will not return undefined if you return add. The toString and valueOf would pick it up. – epascarello Sep 12 '22 at 16:01
  • Yes you are right, I could have return `add` and let `toString` method to cover use case. That would make function simpler. You are right :) – Ivan Vasiljevic Sep 12 '22 at 16:32
0

Using toString ad valueOf to get the result out. Using curried function with spread to get the passed in values as an array. Using reduce to do the addition.

function sum(...args){
    let v = 0;
    const f = (...args) => {
      v = args.reduce((x,n) => x + n, v);
      return f;
    };
    f.valueOf = f.toString = () => v;
    return f.apply(f, args);
}

console.log(sum())
console.log(sum()())
console.log(sum(1));
console.log(sum(1)());
console.log(sum(1)(2)()); 
console.log(sum(1, 2)()); 
console.log(sum(1)(2)(3)()); 
console.log(sum(1)(2, 3)()); 
console.log(sum(1)(2, 3)); 
console.log(sum(1)(2)(3)(4)()); 
console.log(sum(1)(2, 3, 4)());
console.log(sum(1, 2, 3, 4)()); 
console.log(sum(1, 2, 3, 4));
epascarello
  • 204,599
  • 20
  • 195
  • 236
  • hi @epascarello, thank you so much for the reply with explanation, but a little doubt, if I run this code in vscode or also in online console like (stackblitz, condensandbox, stackblitz etc...) then getting ```f sum(...args){}``` and if I run your code then it is working properly. means why its not getting the exact result in vscode, which I am getting here – Amit Sharma Sep 12 '22 at 16:59
  • 1
    Means the console line is not calling toString or toValue. Could be forced to do it with a character like `console.log(+sum(1)(2)()); ` – epascarello Sep 12 '22 at 17:23
-1

does this helps!

function curry(f) {
  return function(a) {
    return function(b) {
        /*return function(c) {
                return function(d) {
            return f(a, b, c, d);
        }       
      }*/      
      return f(a, b);
    };
  };
}

// usage
function sum(a, b /*, c, d*/) {
    if(a && b /*&& c && d*/) {
    return a + b; // + c + d;
  } else {
  return 0;
  }
  
}

const curriedSum = curry(sum);

document.write( curriedSum()() );