2010-09-26 12 views
6

principiante in JS :) ha bisogno di una spiegazione del pezzo di codice da Crockford's book, sezione 4.15:Spiegazione sull'esempio "JavaScript - Le parti buone" (sezione 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); 
}); 

Domanda: Come calcoliamo Fibonacci (15), e se è semplice Fibonacci (15) chiama, quindi come funziona in dettaglio?

Grazie per l'aiuto.

+1

fibonacci (15)? – spender

+0

Mi aspetto che il libro entri nei dettagli su come funziona la funzione - c'è qualcosa in particolare che non capisci? – Douglas

+1

Ehi, di recente ho fatto un video breve Memoizzazione di base utilizzando JavaScript - forse aiuta a capire memoizer: https://www.youtube.com/watch?v=lsp82x0XdsY –

risposta

1

come i commenti alla tua domanda suggeriscono, si deve camminare attraverso il codice in un debugger per ottenere una buona comprensione di ciò che sta succedendo, se potete segui la spiegazione nel libro. Ma ti darò una breve panoramica di quello che sta succedendo:

Ciò che viene dimostrato è la "memoria", una tecnica di ottimizzazione comune utilizzata nella programmazione funzionale. Si dice che una funzione sia pura se il risultato dipende solo dagli argomenti passati in esso. Quindi, se una funzione è pura, puoi mettere in cache il risultato basato sugli argomenti - questa tecnica è chiamata memoisation. Lo farebbe se una funzione è costosa da calcolare e viene chiamata più volte.

L'esempio classico utilizzato per dimostrare questo (come qui) sta generando Fibonacci numbers. Non ho intenzione di passare attraverso come quelli sono risolti, ma in fondo, come si va a numeri sempre più elevati si ripeterti sempre di più come ogni numero viene calcolato dalla precedono due numeri. Con memoising ogni risultato intermedio è sufficiente calcolare una volta rendendo quindi l'algoritmo molto più veloce (molto, molto più veloce, come si va più in alto la sequenza).

Per quanto riguarda questo codice, il memoizer utilizza due parametri: "memo" che è la cache. In questo caso sta entrando con i primi due valori già compilati in '[0,1]' - questi sono i primi due numeri di Fibonacci.

Il secondo parametro è la funzione a cui verrà applicato il memoizzazione. In questo caso una funzione ricorsiva di Fibonacci:

function (shell, n) { shell di ritorno (n - 1) + shell (n - 2); }

ovvero il risultato è la somma dei due numeri precedenti nella sequenza.

Il memoizzatore prima controlla se ha già un risultato memorizzato nella cache. Se lo fa, lo restituisce immediatamente. In caso contrario, calcola il risultato e lo memorizza nella cache. Senza farlo ripetersi ripetutamente e rapidamente diventa incredibilmente lento una volta per arrivare ai numeri più alti nella sequenza.

+1

grazie per la tua risposta. Comunque la mia parte vaga era diversa, ma l'ho già capito da sola:) ... Mi chiedevo come "15" venga passato nel corpo della funzione "memoizer" quando viene chiamato 'fibonacii (15)'. La risposta è banale :): 'memoizer' restituisce una' function (n) '(variabile' shell'), quindi var 'fibonacci' a cui è assegnata una' function (n) 'restituita da' memoizer' accetta 'n = 15 '. – Max

+0

@MaxP. il tuo commento è persino più utile della risposta poiché era il problema che stavo avendo, specialmente dal momento che il libro non fornisce l'istruzione di invocazione1 – LogixMaster

1

per valutare la funzione, è sufficiente chiamare:

fibonacci(15); 

Se si vuole vedere il risultato, il modo più semplice sarebbe:

alert(fibonacci(15)); 

Se si vuole fare questo più spesso, quindi scaricare Firebug, e fare questo in fondo lo script:

Console.log(fibonacci(15)); 

Oppure digita questo direttamente nella console di Firebug, e quindi premere Ritorno:

fibonacci(15) 
+1

grazie per il commento, mi domanda un po 'modificato. Preferisco ascoltare una spiegazione dettagliata del perché la chiamata di fibonacci (15) funzioni? L'operazione 'shell' &'n' è vaga per me ... – Max

+0

Abbastanza sicuro che stia cercando qualcuno che gli faccia capire come funziona il codice, usando' 15' come input di esempio – meagar

+1

Per vedere come funziona in dettaglio assoluto, potresti di nuovo scarica Firebug, quindi esegui una chiamata a fibonacci (15) usando il debugger. Cerca il pulsante Step Into. È possibile aggiungere un'espressione di controllo "n" per mostrare quale è il valore di n è come cambia. – Douglas

3

Ecco una versione annotata di console.log() che tenta di mostrare come viene restituita la pila e assegna il risultato di (n-1) + (n-2) all'array memo per ciascuna rispettiva chiamata ricorsiva. Ricorda inoltre che lo stack ritorna in ordine inverso. Quindi, in uscita il login vedrete l'ultima chiamata restituito prima:

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

Sembra che siete confusi sul perché l'invocazione fibonacci(15) opere. Semplifichiamo il codice (dimentica la memoizzazione per un secondo).

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

Fondamentalmente stiamo impostando f al valore di ritorno della funzione m(). In questo caso, quel valore di ritorno è una funzione. Vedi, possiamo semplificare ulteriormente come:

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

In altre parole, stiamo impostando f ad essere una funzione che prende in un parametro. Stiamo facendo la stessa cosa nell'esempio fibinacci. Questo è il motivo per cui l'invocazione fibonacci(15) funziona.

Problemi correlati