2009-04-06 11 views
5

estaba leyendo elocuente JavaScript y me encontré con este ejemplo para el rompecabezas:¿Una explicación más clara para la recursividad y el flujo de ejecución en JavaScript?

consideran este rompecabezas: Partiendo de el número 1 y en repetidas ocasiones, ya sea la adición de 5 o multiplicar por 3, una cantidad infinita de los nuevos números pueden ser producidos. ¿Cómo escribiría una función que, dado un número, intente para encontrar una secuencia de adiciones y multiplicaciones que producen ese número ?

Aquí está el código para la solución:

function findSequence(goal) { 
    function find(start, history) { 
    if (start == goal) 
     return history; 
    else if (start > goal) 
     return null; 
    else 
     return find(start + 5, "(" + history + " + 5)") || 
      find(start * 3, "(" + history + " * 3)"); 
    } 
    return find(1, "1"); 
} 

print(findSequence(24)); 

Podría alguien aclarar cómo encontrar DoD se ejecutan si no tiene un valor para los parámetros start y la meta? ¿Cómo sucedió la recursión?

+0

Vea también [¿Cómo funciona esta recursión?] (Http://stackoverflow.com/q/15712230/1048572) y [Recursión de Javascript de Eloquent Javascript] (http://stackoverflow.com/q/26205376/1048572) – Bergi

Respuesta

5

Pero find no ha podido ejecutar sin un valor para start y goal. Primero se ejecutó con el valor 1 para start, y el único valor para goal fue 24.

Quizás esté confundido con el orden de las operaciones. Ahí vemos la declaración de una función, findSequence. Durante la declaración, no se ejecuta código. La función findSequence solo se ejecuta más tarde, en la última línea, donde se imprime el resultado de ejecutar la función.

Dentro de la declaración de findSequence, hay una declaración de otra función, find. Una vez más, no se ejecuta hasta más tarde. La función findSequence tiene solo una línea de código ejecutable, la que llama a find(1, "1"). La ejecución de esa línea activa la ejecución de find algunas veces, recursivamente.La función find hace referencia a goal; cuando el intérprete de Javascript ejecuta el código, goal siempre se refiere al parámetro findSequence, y como en este ejemplo findSequence solo se llama una vez, goal siempre tiene el mismo valor, 24.

Debería poder ver dónde ocurrió la recursión. Si start fue igual a goal, entonces la función se detiene; devuelve la historia de cómo llegó a ese número. Si start es mayor que goal, devuelve null, lo que indica que esa ruta no era una ruta hacia el número de destino. Si start aún es menor que goal, la función intenta llamarse a sí mismo con su valor de inicio más 5. Si eso devuelve un valor no nulo, eso es lo que se devuelve. De lo contrario, intenta multiplicar por 3 y devolver ese valor de historial en su lugar.

Tenga en cuenta que aunque este código puede devolver muchos números, no puede devolver todos los números. Si el objetivo es 2, por ejemplo, findSequence devolverá null porque no hay manera de comenzar en 1 y obtener 2 al agregar 5 o multiplicar por 3.

+0

¡Eso lo solucionó! Gracias por la explicación :) – ajushi

+0

'return find (start + 5," ("+ history +" + 5) ") || find (start * 3, "(" + history + "* 3)") ', ¿cómo funciona esta línea? – user7104874

1

Cuando se llama a find dentro de findSequence, tiene acceso a la variable objetivo que se establece en la definición de findSequence. Un ejemplo sencillo de esto es:

function outerFunction() { 
    var a = 2; 
    function innerFunction() { 
    alert(a); 
    } 
    innerFunction(); 
} 
outerFunction(); 

La variable de arranque se define cuando lo hace:

return find(1, "1"); 

tener efectivamente una variable de arranque inicial de 1, la variable objetivo de 24, y una historia de "1 "en el primer pase.

EDITAR: Según el comentario de Rob, los cierres no son realmente lo que está causando esto aquí, ya que find() no se está ejecutando fuera de findSequence(), el alcance hace que se encuentre el objetivo.

+0

¿Eso realmente tiene algo que ver con los cierres? Creo que es solo una resolución de alcance ordinaria: "encontrar" no tiene un identificador de "objetivo" propio, por lo que se resuelve al que está en el alcance adjunto. Los cierres solo se aplicarían si "find" se llamara indirectamente después de que "findSequence" ya había regresado. –

+0

sí en realidad, eso es cierto, no es un problema de cierres, solo un problema de alcance –

0

Si entiendo su pregunta correctamente: La última línea de código está llamando a findSequence(), con un objetivo de 24. En findSequence() hay una función llamada find(), que se define y luego se llama en instrucción de retorno para findSequence, con arranque equivalente a 1, y la historia igualando 1.

Cuestiones relacionadas