Javascript function challenge add(1,2) and add(1)(2) both should return 3

MicFin picture MicFin · Jul 9, 2015 · Viewed 9.8k times · Source

A friend of mine challenged me to write a function that works with both of these scenarios

add(2,4)  // 6
add(2)(4) // 6

My instinct was the write an add() function that returns itself but I'm not sure I'm heading in the right direction. This failed.

function add(num1, num2){
    if (num1 && num2){
        return num1 + num2;
    } else {
        return this;
    }
}

alert(add(1)(2));

So I started reading up on functions that return other functions or return themselves.

I am going to keep trying, but if someone out there has a slick solution, I'd love to see it!

Answer

Patrick Roberts picture Patrick Roberts · Jul 9, 2015

I wrote a curried function whose valueOf() method and function context (this) are bound with the sum no matter how many arguments are passed each time.

/* add function */
let add = function add(...args) {
  const sum = args.reduce((acc, val) => acc + val, this);
  const chain = add.bind(sum);
  chain.valueOf = () => sum;
  return chain;
}.bind(0);

/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));

The reason why both mechanisms are required is because the body of add() must use the called function's bound context in order to access the sum of the intermediate partial application, and the call site must use the valueOf() member (either implicitly or explicitly) in order to access the final sum.