2010-09-26 5 views
6

Początkujący w JS :) potrzebuje wyjaśnienia kawałka kodu z Crockford's book, rozdział 4.15:Wyjaśnienie dotyczące przykładu "JavaScript - dobre części" (rozdział 4.15)?

var memoizer = function (memo, fundamental) { 
    var shell = function (n) { 
     var result = memo[n]; 
     if (typeof result !== 'number') { 
      result = fundamental(shell, n); 
      memo[n] = result; 
     } 
     return result; 
    }; 
    return shell; 
}; 

var fibonacci = memoizer([0, 1], function (shell, n) { 
    return shell(n - 1) + shell(n - 2); 
}); 

Pytanie: Jak obliczyć Fibonacciego (15), a jeśli jest to proste Fibonacci (15) zadzwonić, a następnie, jak to działa w szczegółach?

Dzięki za pomoc.

+1

fibonacci (15)? – spender

+0

Spodziewałbym się, że książka zajmie się szczegółami na temat działania tej funkcji - czy jest coś, czego w szczególności nie rozumiesz? – Douglas

+1

Hej, niedawno nakręciłem krótki film o podstawowej pamięci za pomocą javascript - może to pomaga zrozumieć memoizer: https://www.youtube.com/watch?v=lsp82x0XdsY –

Odpowiedz

1

jako komentarze do Twojego pytania sugerują, należy przejść przez kod w debuggera aby uzyskać dobre zrozumienie tego, co się dzieje, jeśli potrafisz postępuj zgodnie z wyjaśnieniem w książce. Ale dam ci krótki przegląd tego, co się dzieje:

To, co zostało zademonstrowane, to "memoizacja", która jest powszechną techniką optymalizacji stosowaną w programowaniu funkcjonalnym. Mówi się, że funkcja jest czysta, jeśli wynik zależy tylko od przekazanych do niej argumentów. Tak więc, jeśli funkcja jest czysta, możesz buforować wynik na podstawie argumentów - ta technika nazywana jest memoizacją. Można to zrobić, jeśli funkcja jest kosztowna do obliczenia i jest wywoływana wiele razy.

Klasyczny przykład użyty do zademonstrowania tego (jak tutaj) generuje Fibonacci numbers. Nie będę się zastanawiać nad tym, jak te są wypracowane, ale w zasadzie, gdy idziesz do coraz wyższych liczb, powtarzasz się coraz bardziej, ponieważ każda liczba jest obliczana z wcześniejszych dwóch liczb. Zapamiętując każdy wynik pośredni, trzeba je obliczyć tylko raz, co sprawia, że ​​algorytm jest znacznie szybszy (znacznie, dużo szybciej, gdy idziesz wyżej w górę sekwencji).

W odniesieniu do tego kodu, narzędzie do zapisywania zajmuje dwa parametry - "memo", które jest pamięcią podręczną. W tym przypadku zaczyna się od pierwszych dwóch wartości już wypełnionych "[0,1]" - są to pierwsze dwie liczby Fibonacciego.

Drugi parametr to funkcja, do której zostanie zastosowana funkcja zapamiętywania. W tym przypadku funkcja rekurencyjna Fibonacci:

funkcja (powłoka, n) { powłoka powrotna (n - 1) + powłoka (n - 2); }

tj. Wynik jest sumą dwóch poprzednich liczb w sekwencji.

Pierwszy moduł do sprawdzania, czy ma już wynik w pamięci podręcznej. Jeśli to zrobi, natychmiast to zwróci. Jeśli nie, oblicza wynik i przechowuje go w pamięci podręcznej. Bez tego powtarzaliby się raz za razem i szybko osiągali niewiarygodnie powolne tempo, aby dotrzeć do wyższych liczb w sekwencji.

+1

dzięki za odpowiedź. Jednak moja niejasna część była inna, ale dostałem ją już osobiście:) ... Zastanawiałem się, w jaki sposób '15' przechodzi w ciało funkcji' memoizer', gdy wywoływana jest 'fibonacii (15)'. Odpowiedź jest banalna :): 'memoizer' zwraca' function (n) '(zmienna' shell'), więc var 'fibonacci', któremu przypisano' function (n) 'zwróconą przez' memoizer' akceptuje 'n = 15 '. – Max

+0

@MaxP. Twój komentarz jest nawet bardziej przydatny niż odpowiedź, ponieważ był to problem, który miałem, zwłaszcza, że ​​książka nie zawiera instrukcji inwokacji1 – LogixMaster

1

Aby ocenić funkcję, po prostu trzeba to nazwać:

fibonacci(15); 

Jeśli chcesz zobaczyć wynik, najprostszym sposobem byłoby:

alert(fibonacci(15)); 

Jeśli chcesz to zrobić częściej, a następnie pobrać Firebug, i robią to na dole skryptu:

Console.log(fibonacci(15)); 

lub wpisać go bezpośrednio do konsoli Firebug, a następnie naciśnij klawisz Return:

fibonacci(15) 
+1

dzięki za komentarz, nieznacznie zmodyfikowałem pytanie. Chciałbym usłyszeć szczegółowe wyjaśnienie, dlaczego wywołanie fibonacci (15) działa? Operacja 'shell' &' n jest dla mnie niejasna ... – Max

+0

Jestem pewien, że szuka kogoś, kto poprowadzi go przez proces działania kodu, używając '15' jako przykładowego wejścia – meagar

+1

Aby zobaczyć, jak działa w absolutnej szczegółowości, możesz ponownie pobierz Firebuga, a następnie przejdź przez wywołanie programu fibonacci (15) za pomocą debuggera. Poszukaj przycisku Step Into. Możesz dodać wyrażenie zegarka "n", aby pokazać, jaka jest wartość n, gdy się zmienia. – Douglas

3

Oto wersja z adnotacjami o numerach console.log(), która próbuje pokazać, w jaki sposób stos powraca i przypisuje wynik (n-1) + (n-2) do tablicy notatek dla każdego odpowiedniego wywołania rekursywnego. Pamiętaj również, że stos powraca w odwrotnej kolejności. Więc w zalogowanego wyjściem zobaczysz ostatnie wezwanie powrócił pierwszy:

var memoizer = function (memo, fundamental) { 
    var shell = function (n) { 
     var result = memo[n]; 
     if (typeof result !== 'number') { 
      result = fundamental(shell, n); 
      console.log("Hence 'shell(n-1)+shell(n-2)' results in the assignment memo["+n+"]="+result); 
      memo[n] = result; 
     } 
     return result; 
    }; 
    return shell; 
}; 
var fibonacci = memoizer([0, 1], function (shell, n) { 
    console.log("shell is called, and 'n' is equal to --> " + n + "\n" + "At this point shell(n-1)="+shell(n-1)+" AND shell(n-2)="+shell(n-2)); 
    return shell(n - 1) + shell(n - 2);  
}); 
1

Wygląda na to, że jesteś zdezorientowany dlaczego pw fibonacci(15) prac. Uprośćmy kod (zapomnij o zapamiętywaniu przez sekundę).

var m = function() { 
    var s = function (n) { 
     console.log(n); 
    }; 
    return s; 
}; 
var f = m(); 

Zasadniczo jesteśmy ustawienie f do wartości zwracanej funkcji m(). W tym przypadku ta zwracana wartość jest funkcją. Zobacz, moglibyśmy go uprościć dalej jako:

var f = function (n) { console.log(n); }; 

Innymi słowy, jesteśmy ustawienie f być funkcja, która odbywa się w jednym parametrem. Robimy to samo na przykładzie fibinacci. Dlatego działa inwokacja fibonacci(15).