2010-09-26 5 views
6

Principiante en JS :) necesita una explicación de la pieza de código de Crockford's book, la sección 4.15:Explicación sobre el ejemplo de "JavaScript: las piezas buenas" (sección 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); 
}); 

Pregunta: ¿Cómo calculamos Fibonacci (15), y si se trata de Fibonacci sencilla (15) llamar, ¿cómo funciona en detalle?

Gracias por la ayuda.

+1

fibonacci (15)? – spender

+0

Espero que el libro entre en detalles sobre cómo funciona la función. ¿Hay algo en particular que no comprenda? – Douglas

+1

Hola, recientemente realicé un breve video sobre la memorización básica mediante javascript. Quizás ayude a entender el memoizer: https://www.youtube.com/watch?v=lsp82x0XdsY –

Respuesta

1

Como los comentarios a su pregunta sugieren, debe caminar a través del código en un depurador para obtener una buena comprensión de lo que está pasando, si puede Sigue la explicación en el libro. Pero le daré una breve descripción de lo que está sucediendo:

Lo que se está demostrando es 'memorización', que es una técnica de optimización común utilizada en la programación funcional. Se dice que una función es pura si el resultado depende solo de los argumentos que se pasan a ella. Por lo tanto, si una función es pura, puede almacenar en caché el resultado en función de los argumentos; esta técnica se denomina memorización. Haría esto si una función es costosa de calcular y se llama varias veces.

El ejemplo clásico utilizado para demostrar esto (como aquí) es generar Fibonacci numbers. No voy a ver cómo se resuelven esos problemas, pero básicamente, a medida que avanzas en números cada vez más altos, te repites cada vez más a medida que se calcula cada número a partir de los dos números precedentes. Al recordar cada resultado intermedio, solo tiene que calcularlos una vez, lo que hace que el algoritmo sea mucho más rápido (mucho, mucho más rápido a medida que avanza en la secuencia).

En lo que respecta a este código, el memoial toma dos parámetros: 'memo' que es la caché. En este caso, entra con los dos primeros valores que ya se han llenado en '[0,1]': estos son los dos primeros números de Fibonacci.

El segundo parámetro es la función a la que se aplicará la memorización. En este caso, una función de Fibonacci recursiva:

función (shell, n) { shell de retorno (n - 1) + shell (n - 2); }

es decir, el resultado es la suma de los dos números anteriores de la secuencia.

El memoizer primero de los controles para ver si ya tiene un resultado en caché. Si lo hace, lo devuelve inmediatamente. Si no, calcula el resultado y lo almacena en el caché. Sin hacer esto, se repetiría una y otra vez y rápidamente se vuelve imposiblemente lento una vez para llegar a los números más altos en la secuencia.

+1

gracias por su respuesta. Sin embargo, mi parte difusa era diferente, pero ya la obtuve yo sola:) ... Me preguntaba cómo '15' pasa al cuerpo de la función' memoizer' cuando se llama a 'fibonacii (15)'. La respuesta es trivial :): 'memoizer' devuelve una' function (n) '(' shell' variable), por lo que var 'fibonacci' a la que se asigna' function (n) 'devuelta por' memoizer' acepta 'n = 15 '. – Max

+0

@MaxP. su comentario es incluso más útil que la respuesta, ya que era el problema que tenía también, especialmente porque el libro no proporciona la declaración de invocación1. – LogixMaster

1

Para evaluar la función, sólo hay que llamar:

fibonacci(15); 

Si desea ver el resultado, la forma más sencilla sería:

alert(fibonacci(15)); 

Si quieres hacer esto más a menudo, a continuación, descargar Firebug, y hacer esto en la parte inferior de su script:

Console.log(fibonacci(15)); 

O escribe esta directamente en la consola de Firebug, y presione ENTRAR:

fibonacci(15) 
+1

gracias por sus comentarios, modifiqué ligeramente la pregunta. Me gustaría escuchar una explicación detallada de por qué funciona la llamada fibonacci (15). 'shell' &' n' operación es impreciso para mí ... – Max

+0

Bastante seguro de que está buscando a alguien que lo guíe a través de cómo funciona el código, usando '15' como entrada de muestra – meagar

+1

Para ver cómo funciona en absoluto detalle, podría nuevamente descargue Firebug, luego haga una llamada a fibonacci (15) usando el depurador. Busque el botón Paso a paso. Puede agregar una expresión de reloj "n" para mostrarle el valor de n a medida que cambia. – Douglas

3

Aquí hay una versión anotada console.log() que intenta mostrar cómo la pila regresa y asigna el resultado de (n-1) + (n-2) a la matriz de notas para cada llamada recursiva respectiva. Recuerde también que la pila vuelve en orden inverso. Así que en la salida conectado verá la última llamada devuelta primero:

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

Parece que usted está confundido acerca de por qué la invocación fibonacci(15) obras. Simplifiquemos el código (olvídese de la memorización por un segundo).

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

Básicamente estamos estableciendo f que el valor de retorno de la función m(). En este caso, ese valor de retorno es una función. Vemos, podríamos simplificarlo aún más como:

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

En otras palabras, estamos estableciendo f ser una función que toma en un parámetro. Estamos haciendo lo mismo en el ejemplo de fibinacci. Es por eso que funciona la invocación fibonacci(15).

Cuestiones relacionadas