Ich versuche eine Funktion zu schreiben, die den Code auswertet und die Ergebnisse speichert, einschließlich aller möglichen Zustände, die im Code angezeigt werden. Ich habe das funktioniert völlig in Ordnung, außer für die Situation, wenn meine Funktion (nennen wir es evalcapt
) innerhalb einer Fehlerbehandlung Ausdruck ausgeführt wird.
Das Problem ist, dass withCallingHandlers
weiterhin nach übereinstimmenden Bedingungshandlern sucht. Wenn jemand einen solchen Handler außerhalb meiner Funktion definiert hat, verliert meine Funktion die Kontrolle über die Ausführung. Hier ist ein vereinfachtes Beispiel für das Problem:
Funktioniert wie erwartet
%Vor%aber:
%Vor%Funktioniert nicht:
%Vor% Was ich wirklich brauche, ist eine Möglichkeit, einen Neustart zu definieren, direkt nachdem die Bedingung im Code signalisiert wurde. Offensichtlich funktioniert withCallingHandlers
normal (wenn mein Handler der letzte verfügbare Handler ist), aber ich weiß nicht, Ich sehe den Neustart, der eingerichtet wird, wenn ich browse
in meiner Handling-Funktion verwende und computeRestarts
verwende.
tryCatch
tryCatch
hat nicht das gleiche Problem wie withCallingHandlers
, weil es nicht weiter nach Handlern sucht, nachdem es die erste gefunden hat. Das große Problem mit ist es auch nicht weiter den Code nach der Bedingung zu bewerten. Wenn Sie sich das Beispiel ansehen, das oben funktioniert hat, aber sub in tryCatch
für withCallingHandlers
, wird der Wert (25) nicht zurückgegeben, da die Ausführung wieder in den tryCatch
-Frame gebracht wird, nachdem die Bedingung bearbeitet wurde.
Im Grunde suche ich nach einer Mischung zwischen tryCatch
und withCallingHandlers
, eine, die die Kontrolle an den Condition Signaler zurückgibt, aber auch nach mehr Handlern sucht, nachdem die erste gefunden wurde.
tryCatch
Okay, aber wie brechen Sie auf (und komplexere Funktionen mit signalisierten Bedingungen überall):
%Vor% Ich habe nach dem Quellcode gesucht, der mit dem .Internal(.signalCondition())
-Aufruf verbunden ist, um zu sehen, ob ich herausfinden kann, ob es einen Neustart hinter den Kulissen gibt, aber ich bin da nicht richtig. Es scheint wie:
von src / main / errors.c macht etwas von diesem Neustart-Aufruf, und dies wird von do_signalCondition
aufgerufen, aber ich habe keine Ahnung, wie ich damit umgehen würde.
Ich denke, was Sie suchen, ist withRestarts
zu verwenden, wenn Ihre spezielle Bedingung signalisiert wird, wie von warning
:
so
%Vor%führt zu
%Vor% Soweit ich das beurteilen kann, gibt es keine einfache Lösung für dieses Problem (ich bin froh, dass ich mich als falsch erwiesen habe). Die Ursache des Problems ist zu sehen, wenn wir uns ansehen, wie tryCatch
und withCallingHandlers
die Handler registrieren:
Der entscheidende Punkt ist das letzte Argument, FALSE in tryCatch
, TRUE in withCallingHandlers
. Dieses Argument führt zu dem gp
-Bit Einstellung von do_addCondHands
& gt; mkHandlerEntry
in src / main / fehler.c.
Dasselbe Bit wird dann von do_signalCondition
(immer noch in src / main / errors.c) abgefragt, wenn eine Bedingung signalisiert wird:
Wenn das GP-Bit gesetzt ist, werten wir den Handler aus und durchlaufen den Handler-Stack. Wenn es nicht gesetzt ist, dann führen wir gotExitingHandler
aus, das den Handler ausführt, aber dann die Kontrolle an die Handlingskontrollstruktur zurückgibt, anstatt den Code wieder aufzunehmen, in dem die Bedingung signalisiert wurde.
Da das GP-Bit Ihnen nur eines von zwei Dingen sagen kann, gibt es keine direkte Möglichkeit, das Verhalten dieses Aufrufs zu ändern (dh Sie durchlaufen entweder alle Handler, wenn Sie withCallingHandlers
verwenden, oder Sie stoppen bei erster passender Eintrag von tryCatch
).
Ich habe mit der Idee von trace
ing signalConditions
gespielt, um dort einen Neustart hinzuzufügen, aber das scheint zu hackisch zu sein.
Tags und Links r exception-handling try-catch