2017-01-30 4 views
6

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

sum(4)() // 4 
sum(4)(5)() // 9 
sum(4)(5)(9)() // 18 
sum(4)(5)(9)(1)() // 19 
// etc... 

Проблема упрощается при вызове разрешенной пустой функции в конце как признак конца вызовов ,

Я работал над решением, которое делает работу, но используя глобальные переменные внутри самой функции:

var sum = function (a) { 
    if (!sum.init) { 
     sum.total = 0; 
     sum.init = true; 
    } 
    if (!arguments.length) { 
     sum.init = false; 
     return sum.total; 
    } 
    sum.total += a; 
    return sum; 
}; 

Это решение работает, но использует состояние, глобальные переменные и функции объекта фокусы, не является идеальным. Мой вопрос здесь в том, есть ли способ решить проблему чисто рекурсивным образом.

В качестве побочного примечания я не считаю, что проблема может быть решена, если этот последний пустой вызов () не предоставляется, но если я ошибаюсь, сообщите мне.

Update

Этот вопрос был дан ответ на Просмотр Кода: https://codereview.stackexchange.com/a/153999/129579

неет решение, которое не опирается на глобальную область видимости и является чисто функциональным.

+3

Это выглядит, как он относится на Просмотр Кода – mplungjan

+0

Может быть стоит в том числе ссылке://codereview.stackexchange.com/ –

+1

Вы изучали карри? – epascarello

ответ

3

Вы можете использовать закрытия для того чтобы достигнуть того, что вы хотите, как это:

function sum(value){ 
 
    // the closure variable that will be accessible for all the _sum calls (initialised to 0 for every sum call). 
 
    var result = 0; 
 
    
 
    // the function that will be returned (sum will only get called once to initialize the result to 0. It's _sum which will be returned as much as possible) 
 
    function _sum(a){ 
 
    // if we passed a parameter, then add it to result and return a new _sum 
 
    if(typeof a != "undefined"){ 
 
     result += a; 
 
     return _sum; 
 
    } 
 
    // if we didn't return the result 
 
    else 
 
     return result; 
 
    } 
 
    // of course after initializing result we need to call _sum that handle the actual summing and return whatever it returns (if value is defined, it will return another `_sum` if not it will return the value of result which will be 0 at first) from now on sum will have nothing to do with the rest of the calls (()()()...) 
 
    return _sum(value); 
 
} 
 

 
console.log("sum() = " + sum()); 
 
console.log("sum(7)() = " + sum(7)()); 
 
console.log("sum(5)(6)(7)() = " + sum(5)(6)(7)()); 
 

 
// will return 0 because we call sum again 
 
console.log("sum() = " + sum());

Примечание: Это sum(1)(7)(3)()); будет звонить, в следующем порядке:

  1. sum с параметром 1, который будет инициализировать result в 0 и вызвать
  2. _sum с тем же параметром 1 который добавит его result и вернуть новый inctance из _sum, которая будет называться так следующее
  3. _sum дозвонились с параметром 7, добавить это и вернуть новый _sum поэтому новый
  4. _sum дозвонились с параметром 3 ... икру другой
  5. _sum, что не будет иметь параметр, поэтому if(typeof a != "undefined") не удастся, и вместо этого _sum вернет result.

Фактическое значение sum вызывается только в начале, чтобы выполнить инициализацию. Это, как я уже сказал, _sum, которые добираются до конца до конца.

+0

if (a) означает, что 0 вернет результат и сломает цепочку. – Francis

+0

@ Франсис Не думал об этом. Я уточню свой ответ. Благодаря! –

0

В принципе, вы можете использовать внешнюю функцию sum для первоначального вызова и закрытия над начальным значением a и внутренней функции fn, который repeatingly вернулся и только возбужденной если arguments.length равно нуль.

Если задано значение b, то возвращается значение a и возвращается внутренняя функция fn.

function sum(a) { 
 
    return function fn(b) { 
 
     if (!arguments.length) { 
 
      return a; 
 
     } 
 
     a += b; 
 
     return fn; 
 
    }; 
 
} 
 

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

Edit для вызова сумму без аргумента

function sum(a) { 
 
    return arguments.length ? 
 
     function fn(b) { 
 
      if (!arguments.length) { 
 
       return a; 
 
      } 
 
      a += b; 
 
      return fn; 
 
     } : 
 
     0; 
 
} 
 

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

+0

Что делать, если он называет сумму без параметров типа 'sum();'? –

+0

см. Второй подход, он возвращается как ваш, ноль. –