2

I was asked this question in an interview.

for sum(2)(3) in currying style

sum(a) {
  return (b) {
    return a + b;
  }
}

for sum (2, 3)

sum(a, b) {
  return a + b;
}

Is there any common function which can work for both

Barmar
  • 741,623
  • 53
  • 500
  • 612
AkRoy
  • 343
  • 4
  • 10
  • You can make one, but it will be ugly, and imho bad code style. Just check, whether the second parameter is there, and if not, return the function, otherwise the result. – ASDFGerte Oct 01 '19 at 19:27
  • 3
    Check how many [`arguments`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) you got and then return either the result or the inner function. – Bergi Oct 01 '19 at 19:27
  • Maximum 'unification': this can be solved with a single "+" in the code. – user2864740 Oct 01 '19 at 19:29
  • 1
    There's definitely a duplicate somewhere, I know I've answered this before... – Patrick Roberts Oct 01 '19 at 19:29
  • 1
    Possibly relevant: [Generalised Curry - Javascript](https://stackoverflow.com/questions/50616087/generalised-curry-javascript) – VLAZ Oct 01 '19 at 19:31

6 Answers6

3

Here's a function that can create a generalized curried function from any non-curried function. It is written without using any ECMAScript 6 syntax. This works regardless of the number of parameters expected by the original function, or the number of arguments provided to each partial application.

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

function product (a, b, c) {
  return a * b * c;
}

function curry (fn) {
  return function partial () {
    if (arguments.length >= fn.length) {
      return fn.apply(this, arguments);
    }

    var partialArgs = Array.prototype.slice.call(arguments);
    var bindArgs = [this].concat(partialArgs);
    return partial.bind.apply(partial, bindArgs);
  };
}

var s = curry(sum);

console.log(s(1, 2));
console.log(s(1)(2));
console.log(s()()(1)()()(2));

var p = curry(product);

console.log(p(2, 3, 4));
console.log(p(2)(3)(4));
console.log(p()()(2)()()(3, 4));
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
2

There is a way, but it is quite hacky...

You can always check that a second argumet has been passed to your function and react accordingly

function sum(a, b){
    if(b === undefined){
        return (c) => {
            return c + a;
        }
    }

    return a + b;
}
zelitomas
  • 113
  • 8
2

You could return either the sum or a function based on the length of the arguments object.

function sum(a,b) {
  return arguments.length === 2   //were two arguments passed?
    ? a+b                         //yes: return their sum
    : (b) => a+b                  //no:  return a function
};

console.log(sum(3)(5));
console.log(sum(3,5));
Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
0

You can have a function that does both with infinite currying :

the idea here is to return a function as well as a computed value each time, so that if it is called again, the returned function will handle it, and if its not called, the computed value is printed.

function sum(...args) {
  function add(...args2) {
    return sum(...args, ...args2);
  }

  const t = [...args].reduce((acc, curr) => acc + curr, 0);
  add.value = t;

  return add;
}

const result1 = sum(2, 3).value;
const result2 = sum(2)(3).value;
const result3 = sum(2, 3)(4).value;
const result4 = sum(2, 3)(4, 5).value;
const result5 = sum(2, 3)(4, 5)(6).value;

console.log({ result1, result2, result3, result4, result5 });
Taki
  • 17,320
  • 4
  • 26
  • 47
0

you must check if the second argument is defined or not:

const sum = (a,b) => {
  const add1 = (b) => {
      return a+b
  }

return typeof b == 'undefined' ? add1 :   add1(b)   \\if it has the second arg else if it hasn't the second arg so give it the arg\\

}

Saeid Shoja
  • 159
  • 2
  • 8
0

Hope so it will help you

    const sum =(a,b)=>{
      return a.reduce((pre,cur)=> pre + cur , b)
    }
    const add=(...a)=> (...b)=> b.length ? add(sum(b,sum(a,0))) : sum(a,0)
    
    console.log(add(2,3,4)(5)(2)(8,6,3,5)())
    console.log(add(2,3,4,5,2,8,6,3,5)())
Mirza Hayat
  • 284
  • 5
  • 11