2009-04-06 5 views
5

Ich war Eloquent JavaScript zu lesen und ich auf dieses Beispiel für das Puzzle kam:Eine klarere Erklärung für Rekursion und Ablauf der Ausführung in JavaScript?

dieses Rätsel vor: von die Nummer 1 und wiederholt Durch das Starten entweder Zugabe von 5 oder 3 multipliziert wird, eine unendliche Menge an Neue Nummern können produziert werden. Wie würden Sie eine Funktion schreiben, die, gegeben eine Zahl, versucht, eine Folge von Hinzufügungen und Multiplikationen zu finden, die diese Zahl produzieren?

Hier ist der Code für die Lösung:

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

Könnte jemand aufklären, wie dod findet ausgeführt werden soll, wenn es keinen Wert für die Argumente beginnen und Ziel hat? Wie ist die Rekursion passiert?

+0

Siehe auch [Wie funktioniert diese Rekursion?] (Http://stackoverflow.com/q/15712230/1048572) und [Javascript Rekursion von Eloquent Javascript] (http://stackoverflow.com/q/26205376/1048572) – Bergi

Antwort

5

Aber findnicht ohne Wert ausgeführt werden soll für start und goal. Es wurde zuerst mit dem Wert 1 für start ausgeführt und der einzige Wert für goal war 24.

Vielleicht sind Sie verwirrt über die Reihenfolge der Vorgänge. Dort sehen wir die Deklaration einer Funktion, findSequence. Während der Deklaration wird kein Code ausgeführt. Die Funktion findSequence wird erst später in der letzten Zeile ausgeführt, in der das Ergebnis der Ausführung der Funktion ausgedruckt wird. In der Deklaration findSequence gibt es eine Deklaration einer anderen Funktion, find. Wiederum wird es erst später ausgeführt. Die findSequence Funktion hat nur eine ausführbare Codezeile, die eine, die aufruft. Die Ausführung dieser einen Zeile löst die Ausführung von find einige Male rekursiv aus.Die find Funktion bezieht sich auf goal; Wenn der Javascript-Interpreter den Code ausführt, bezieht sich goal immer auf den Parameter findSequence, und da in diesem Beispiel findSequence nur einmal aufgerufen wird, hat goal immer den gleichen Wert, 24.

Sie sollten in der Lage zu sehen, wo die Rekursion passiert ist. Wenn start gleich goal war, dann stoppt die Funktion; es gibt die Geschichte zurück, wie es bei dieser Nummer angekommen ist. Wenn start größer als goal ist, gibt es null zurück, um anzuzeigen, dass dieser Pfad kein Pfad zur Zielnummer war. Wenn start ist immer noch weniger als goal, dann versucht die Funktion Aufruf mit seinem Startwert plus 5. Wenn das einen Wert ungleich Null zurückgibt, dann wird das zurückgegeben. Andernfalls wird versucht, mit 3 zu multiplizieren und stattdessen den Verlaufswert zurückzugeben.

Beachten Sie, dass, obwohl dieser Code viele Zahlen zurückgeben kann, nicht alle Zahlen zurückgegeben werden kann. Wenn das Ziel 2 ist, wird findSequence zum Beispiel null zurückgeben, da es keine Möglichkeit gibt, um 1 zu starten und 2 zu erhalten, indem Sie 5 hinzufügen oder mit 3 multiplizieren.

+0

Das hat die Dinge aufgeräumt! Danke für die Erklärung :) – ajushi

+0

'return find (start + 5," ("+ history +" + 5) ") || find (start * 3, "(" + history + "* 3)") ", wie funktioniert diese Linie? – user7104874

1

Wenn find innerhalb von findSequence aufgerufen wird, hat es Zugriff auf die Zielvariable, die in der Definition von findSequence festgelegt ist. Ein einfaches Beispiel hierfür ist:

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

Die Startvariable definiert ist, wenn es funktioniert:

return find(1, "1"); 

effektiv eine anfängliche Startvariable 1, Ziel variabel von 24 und eine Geschichte von „1 mit "Im ersten Durchgang.

EDIT: Per Robs Kommentar, Schließungen sind nicht das, was dies hier verursacht, da find() nicht außerhalb von findSequence() ausgeführt wird, verursacht Scoping, dass das Ziel gefunden wird.

+0

Hat das wirklich etwas mit Verschlüssen zu tun? Ich denke, es ist nur normale Auflösung des Bereichs: "Find" hat keine eigene "Ziel" -Kennung, so dass es zu dem im umschließenden Bereich aufgelöst wird. Closures würden nur gelten, wenn "find" indirekt aufgerufen würde, nachdem "findSequence" bereits zurückgegeben wurde. –

+0

ja eigentlich, das ist wahr, es ist kein Verschlüsse Problem, nur ein Problem Bereicherung –

0

Wenn ich deine Frage richtig verstehe: Die letzte Codezeile ruft findSequence() mit einem Ziel von 24 auf. In findSequence() gibt es eine Funktion namens find(), die definiert und dann aufgerufen wird return-Anweisung für findSequence, mit Beginn gleich 1, und die Geschichte gleich 1.