2012-04-04 1 views
3

Gibt es eine einfache Möglichkeit, den Stack in Tcl auszuwickeln? Ich habe dieses merkwürdige Problem, wo ich buchstäblich zu einem bestimmten Stapelrahmen zurückkommen muss. Ich kann alle Rahmeninformationen unter Verwendung des Befehls info erhalten, aber um tatsächlich zu einem bestimmten Rahmen zu gelangen, muss ich einige lokale Variablen in jeder Prozedur einstellen und sie entsprechend prüfen. Ich habe mich gefragt, ob es einen leichteren Weg gibt.Zurückspringen zu einem anderen Tcl-Stack-Frame

+0

Zum Debuggen oder ...? –

+0

Zum Laufen. Ich muss von einer Prozedur zu einer anderen auf einer anderen Ebene gelangen. – ilya1725

+0

Während ich denke, dass die Antwort der Donal Fellows perfekt ist, sollte das Thema besser umformuliert werden, da "Abrollen des Stapels" ein Begriff ist, der tief mit der Ausnahmebehandlung/dem Debugging in den Köpfen der meisten Programmierer verbunden ist. Irgendeine Idee, wie man vernünftig umformuliert? – kostix

Antwort

4

Wenn Sie Code erhalten müssen, um eine nicht-lokale Rückkehr (dh mehrere Ebenen zurückspringen) zu tun, Sie können dies tun, von 8,5 ab mit der -level Option return . Siehe dieses Beispiel:

Dies funktioniert, indem Sie eine besondere Art von Ausnahme werfen; Die Details sind ziemlich versteckt. Alternativ können Sie auch try und throw verwenden, wenn Sie 8.6 oder eine skriptgesteuerte Implementierung von ihnen haben (siehe Tcler's Wiki für Tcl-Code, der bei der Erörterung des Codes in 8.6 verwendet wurde).

Bei älteren Versionen Tcl, der einfachste Mechanismus ist return -code 42 zu verwenden und einige Codes in Position zu setzen Stapel zu catch die benutzerdefinierten Ausnahme und bestimmen, ob es die Magie Wert (42 hier, sondern das Ergebnis sein wird von die catch) und reagieren entsprechend. Dies kann sehr effektiv sein, ist aber auch unordentlich. Deshalb gibt Ihnen ab 8.5 Werkzeuge, die einfacher zu bedienen sind.

3

Kurze Antwort ist, dass Sie wahrscheinlich besser Ihr Design überdenken würden.

Längere Antwort ist, dass die einzige wirkliche Möglichkeit (ich kann daran denken), dies zu tun, ist es, einen Fehler zu werfen und es auf dem Niveau zu fangen, auf dem Sie es stoppen müssen. Anders als natürlich, die weniger flammen-würdige Art, Variablen den ganzen Call Stack hinauf zu prüfen. Die Verwendung von Fehlern für den Kontrollfluss ist jedoch ... schlechte Form.

1

Wenn Sie bereit sind, modern zu sein, können Coroutinen (verfügbar in 8.6) Ihre Anforderungen erfüllen.

Sonst könnten Sie versuchen, die Ebene der Routine zu notieren, zu der Sie gelangen müssen, wenn Sie dort sind (dh eine globale Variable auf [info level] setzen), und dann im tieferen proc, [ uplevel] zu diesem absoluten Stack-Frame. So etwas wie

proc need-to-be-here {} { 
    set ::myframe [info level] 
    deeper-calls 
} 

proc deepest-call {} { 
    uplevel #$::myframe {what I need to do} 
} 

(ungetestet)

+0

+1 für den bösen Gebrauch von 'uplevel'. Benutze es einfach nicht in irgendeinem Code, den ich pflegen muss! :-) –