Beliebige Bedingungen mit 'withCallingHandlers' erfassen

8

Das Problem

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:

%Vor%

Funktioniert wie erwartet

%Vor%

aber:

%Vor%

Funktioniert nicht:

%Vor%

Eine Lösung, die ich nicht implementieren kann

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.

Dinge, die wie Lösungen aussehen, die nicht funktionieren

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.

Unterteilen Sie den Ausdruck in Unterausdruck und verwenden Sie dann tryCatch

Okay, aber wie brechen Sie auf (und komplexere Funktionen mit signalisierten Bedingungen überall):

%Vor%

Verschiedenes

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:

%Vor%

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.

    
BrodieG 13.12.2013, 17:18
quelle

3 Antworten

4

Ich denke, was Sie suchen, ist withRestarts zu verwenden, wenn Ihre spezielle Bedingung signalisiert wird, wie von warning :

%Vor%

so

%Vor%

führt zu

%Vor%     
Martin Morgan 14.12.2013 01:46
quelle
2

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:

%Vor%

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:

%Vor%

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.

    
BrodieG 03.03.2015 19:56
quelle
1

Mit etwas C können Sie einen Ausdruck in ToplevelExec() auswerten, um ihn von allen im Stack registrierten Handlern zu isolieren.

Wir werden es in der nächsten rlang-Version auf R-Ebene veröffentlichen.

    
lionel 02.10.2017 22:03
quelle

Tags und Links