2017-01-30 18 views
6

W ramach wyzwania programistycznego mamy za zadanie utworzenie funkcji o nieokreślonej liczbie kolejnych wywołań. Jako przykład, powiedzmy, że funkcja zwraca po prostu sumę przewidzianych argumentów, to powinno działać w następujący sposób:Tworzenie funkcji z nieokreśloną liczbą kolejnych wywołań

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

Problemem jest uproszczona przez Dozwolone wywołanie funkcja pusta w końcu jako wskazanie koniec rozmowy .

Pracowałem nad rozwiązaniem, dokłada zadanie, ale przy użyciu zmiennych globalnych wewnątrz funkcji samego:

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; 
}; 

to rozwiązanie działa, ale używa stan, zmienne globalne i funkcja obiektu sztuczek, które nie jest idealny. Moje pytanie dotyczy tego, czy istnieje sposób na rozwiązanie problemu w sposób czysto rekurencyjny.

Na marginesie nie uważam, że problem można rozwiązać, jeśli nie podano ostatniego pustego połączenia (), ale jeśli się mylę, proszę dać mi znać.

Aktualizacja

Kwestia ta została udzielona odpowiedź inspekcja kodu: https://codereview.stackexchange.com/a/153999/129579

Rozwiązanie NEET, które nie opierają się na globalny zasięg i jest czysto funkcjonalne.

+3

wygląda to jak należy się inspekcja kodu – mplungjan

+0

Może warto w tym linku: http://codereview.stackexchange.com/ –

+1

Czy badałeś currying? – epascarello

Odpowiedz

3

Można skorzystać z zamknięć jest osiągnąć to, co chcesz tak:

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());

UWAGA: To sum(1)(7)(3)()); wezwie, w następującej kolejności:

  1. sum z parametrem 1 który zainicjuje result do 0 i nazywają
  2. _sum z tego samego parametru 1 który doda ją do result i powrócić nowego inctance z _sum który będzie nosił nazwę więc następujące
  3. _sum uzyskać wywołana z parametrem 7, dodać to i powrócić nowy _sum więc nowy
  4. _sum uzyskać wywołana z parametrem 3 ... tarło innego
  5. _sum że nie będzie miał parametr, dlatego if(typeof a != "undefined") zakończy się niepowodzeniem, a ten _sum powróci zamiast tego result.

Faktycznie sum jest wywoływany tylko raz na początku, aby wykonać inicjalizację. To, jak już powiedziałem, _sum, które zostają przykute po tym aż do końca.

+0

if (a) oznacza, że ​​0 zwróci wynik i przerwie łańcuch. – Francis

+0

@Francis Nie pomyślał o tym. Zaktualizuję moją odpowiedź. Dzięki! –

0

zasadzie można użyć funkcję sum zewnętrzną dla połączenia początkowego i zamknięcie ponad wartość początkową a i funkcji wewnętrznej fn, który jest zwrócony repeatingly i tylko wyszły jeśli arguments.length jest równa zeru.

Jeśli zostanie podana wartość b, zmienna a zostanie zaktualizowana, a wewnętrzna funkcja zostanie zwrócona.

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)());

Edycja za nazwanie sumę bez argumentu

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

Co, jeśli wywoła on sumę bez parametrów takich jak: 'sum();'? –

+0

proszę zobaczyć drugie podejście, zwraca jako twoje, zero. –

Powiązane problemy