Подтвердить что ты не робот

Функция суммирования варидической карри

Мне нужна функция js sum для работы следующим образом:

sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10 
etc.

Я слышал, что это невозможно. Но слышал, что если добавить + перед sum, можно сделать. Как +sum(1)(2)(3)(4).
Любые идеи о том, как это сделать?

4b9b3361

Ответ 1

Не уверен, что понял, что ты хочешь, но

function sum(n) {
  var v = function(x) {
    return sum(n + x);
  };

  v.valueOf = v.toString = function() {
    return n;
  };

  return v;
}

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

Ответ 2

Это пример использования пустых скобок в последнем вызове в качестве закрытого ключа (из моего последнего интервью):

сумма (1) (4) (66) (35) (3)()

function sum(numberOne) {
  var count = numberOne;
  return function by(numberTwo) {
    if (numberTwo === undefined) {
      return count;
    } else {
      count += numberTwo;
      return by;
    }
  }
}
console.log(sum(1)(4)(66)(35)(3)());

Ответ 3

Я публикую эту ревизию как свой собственный пост, так как у меня, видимо, недостаточно репутации, чтобы просто оставить ее в качестве комментария. Это пересмотр превосходного решения @Rafael.

function sum (n) {
    var v = x => sum (n + x);
    v.valueOf = () => n; 
    return v;
}

console.log(+sum(1)(2)(3)(4)); //10

Я не видел причины держать бит v.toString, поскольку это не казалось необходимым. Если я ошибаюсь при этом, сообщите мне в комментариях, почему требуется v.toString(он прошел мои тесты отлично без него). Преобразование остальных анонимных функций в функции стрелок для удобства чтения.

Ответ 4

Вы можете использовать следующую функцию

function add(num){
   add.sum || (add.sum = 0) // make sure add.sum exists if not assign it to 0
   add.sum += num; // increment it
   return add.toString = add.valueOf = function(){ 
      var rtn = add.sum; // we save the value
      return add.sum = 0, rtn // return it before we reset add.sum to 0
   }, add; // return the function
}

Так как функции являются объектами, мы можем добавлять к ним свойства, которые мы возвращаем, когда они были доступны.

Ответ 5

Вот решение, которое использует ES6 и toString, подобно @Vemba

function add(a) {
  let curry = (b) => {
    a += b
    return curry
  }
  curry.toString = () => a
  return curry
}

console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))

Ответ 6

Чтобы сделать sum(1) вызываемым как sum(1)(2), он должен вернуть функцию.

Функция может быть вызвана или преобразована в число с помощью valueOf.

function sum(a) {

   var sum = a;
   function f(b) {
       sum += b;
       return f;
    }
   f.toString = function() { return sum }
   return f
}

Ответ 7

Так как это общий вопрос для интервью, здесь я беру с использованием свойств функции, чтобы добавить memoization в функцию sum() и немного упростить его код:

function sum(x) {
  sum.result = (sum.result) ? sum.result += x : x;
  sum.valueOf = function() {
    return sum.result;
  }
  return sum;
}

sum(1)(2)(3); // == 6

Ответ 8

Другой немного более короткий подход:

 const sum = a => b => b? sum(a + b) : a;

Используется как:

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

Ответ 9

Вот решение с универсальной функцией variadic curry в ES6 Javascript, с оговоркой, что final () необходим для вызова аргументов:

const curry = (f) =>
   (...args) => args.length? curry(f.bind(0, ...args)): f();
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true

Вот еще один, который не нуждается (), используя valueOf как в ответе @rafael. Я чувствую, что использование valueOf таким образом (или, возможно, вообще) очень сбивает с толку людей, читающих ваш код, но каждый по-своему.

toString в этом ответе не требуется. Внутренне, когда javascript выполняет приведение типов, он всегда вызывает valueOf() перед вызовом toString().


// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );

const curry = autoInvoke((f) =>
   (...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());

const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true

Ответ 10

Может быть старый вопрос, но немного расширенный ответ

function sum() {

    var args = [];
    args.push(...arguments);

    function sumOfAllArguments() {
        return args.reduce((prev,items)=>prev + items, 0)
    }

    function v() {
        arguments && args.push(...arguments);
        return arguments.length === 0 ? sumOfAllArguments() : v;
    }

    v.valueOf = v.toString = sumOfAllArguments;

    return v;

}
        
    

        console.log(sum(2)(2)(2)()) // 6
        console.log(sum(2)(2)(2).toString()) // 6
        console.log(sum(2)(2)(2).valueOf()) // 6
        console.log(+sum(2)(2)(2)) //6
        console.log(sum(2)(2)(2)) // f 6

        console.log(sum(2,2,2)(2,2)(2)) // f 12
        console.log(sum(2)(2,2)(2)()) //  8

Ответ 11

   function sum(a){
    let res = 0;
    function getarrSum(arr){
            return arr.reduce( (e, sum=0) =>  { sum += e ; return sum ;} )
     }

    function calculateSumPerArgument(arguments){
            let res = 0;
            if(arguments.length >0){

            for ( let i = 0 ; i < arguments.length ; i++){
                if(Array.isArray(arguments[i])){
                    res += getarrSum( arguments[i]);
                }
                else{
                  res += arguments[i];
                }
             }
          }
            return res;
     }
    res += calculateSumPerArgument(arguments);



    return function f(b){
        if(b == undefined){
            return res;
        }
        else{
            res += calculateSumPerArgument(arguments);
            return f;
        }
    }

}

Ответ 12

let add = (a) => {
  let sum = a;
  funct = function(b) {
    sum += b;
    return funct;
  };

  Object.defineProperty(funct, 'valueOf', {
    value: function() {
      return sum;
    }
  });
  return funct;
};


console.log(+add(1)(2)(3))

Ответ 13

Вот еще один функциональный способ использования итеративного процесса

const sum = (num, acc = 0) => {
    if (!num) return acc;
    return x => sum(x, acc + num)
}

sum(1)(2)(3)()

и однострочный

const sum = (num, acc = 0) => !num ? acc : x => sum(x, acc + num)

sum(1)(2)(3)()