Warum unterstützt F # natürlich keinen try / with / finally-Block?
Ist es nicht sinnvoll probier etwas aus, deal mit der Ausnahme, die es auslöst, zumindest um die Ausnahme zu protokollieren, und dann sicher dass irgendein Code nach all dem ausgeführt wird?
Sicher, wir können
machen %Vor%Aber das scheint zu künstlich, es zeigt deutlich, dass "F # gegen Versuch / mit / endlich ist". Warum ist das so?
Wie bereits erwähnt, würden Sie normalerweise try-with-finally
verwenden, um sicherzustellen, dass Sie im Falle einer Ausnahme alle Ressourcen ordnungsgemäß freigeben. Ich denke, dass Sie dies in den meisten Fällen mit dem Schlüsselwort use
leichter tun können:
Ich denke, das ist hauptsächlich der Grund, warum Sie try-with-finally
nicht so oft brauchen wie in anderen Sprachen. Aber natürlich gibt es einige Situationen, in denen Sie es brauchen könnten (aber Sie könnten das natürlich vermeiden, indem Sie die Instanz von IDisposable
mit Objektausdrücken erstellen (was syntaktisch sehr einfach ist). Aber ich denke das ist so selten, dass sich das F # -Team nicht wirklich darum kümmern muss.
Orthogonalität? Sie können einfach einen Versuch mit einem Versuch - schließlich, wie Sie zeigen, nisten. (Das ist auf der Ebene der IL sowieso so, denke ich.)
Das heißt, "try-with-finally" ist etwas, das wir in einer zukünftigen Version der Sprache berücksichtigen könnten.
Ich persönlich bin nur darauf gestoßen, es ein paar Mal zu wollen, aber wenn Sie es brauchen, ist es ein wenig lästig, die zusätzliche Verschachtelung / Einrückung zu machen. Im Allgemeinen finde ich, dass ich selten Ausnahmebehandlungscode schreibe, und es ist in der Regel nur der eine oder der andere (zB eine invariante oder andere transaktionale Semantik wiederherzustellen, oder ein 'catch' nahe der Spitze einer App, um eine Ausnahme oder Show zu protokollieren die Benutzerdiagnose).
Aber ich denke nicht, dass es viel zu lesen gibt bezüglich des Sprachdesigns hier.
Ohne ins Detail zu gehen, denn die großartigen Details sind in
Expert .NET 2.0 IL Assembler von Serge Lidin
Siehe: Kap. 14, Verwaltete Ausnahmebehandlung
"Die Handler finally und fault können nicht friedlich mit anderen Handlern koexistieren, wenn also ein geschützter Block einen Fehler oder hat Handler, es kann nichts anderes haben. Um einen finally oder Fehler -Handler mit anderen Handlern zu kombinieren, müssen Sie die geschützten und Handler-Bocks innerhalb anderer geschützter Blöcke verschachteln , ..., so dass jeder finally oder Fehler -Handler seinen eigenen persönlichen geschützten Block hat. "
pg. 300
Ein try / catch verwendet einen Fehler -Handler, und ein try / verwendet schließlich einen finally -Handler.
Siehe: ILGenerator.BeginFaultBlock Methode
Wenn Sie einen Handler Fehler in einem Ausnahmeblock ausgeben, der auch a enthält catch handler oder ein finally -Handler, der resultierende Code ist nicht verifizierbar .
Also könnten alle .net-Sprachen mit syntaktischem Surgar in Betracht gezogen werden, und da F # so neu ist, haben sie es noch nicht implementiert. Nein, schade, nein. Fould.
Ich werde meinen Kommentar in dieser Antwort klären.
Ich behaupte, dass kein Grund zu der Annahme besteht, dass Sie Ausnahmen abfangen und einige Ressourcen auf derselben Ebene abschließen möchten . Vielleicht hast du dich daran gewöhnt, es in einer Sprache zu machen, in der es praktisch war, beides gleichzeitig zu handhaben, aber es ist ein Zufall, wenn es passiert. Die Finalisierung ist praktisch, wenn Sie nicht alle Ausnahmen vom inneren Block abfangen. try...with
dient zum Abfangen von Ausnahmen, damit die Berechnung normal fortgesetzt werden kann. Es gibt einfach keine Beziehung zwischen den beiden (wenn überhaupt, gehen sie in entgegengesetzte Richtungen: fängst du die Ausnahme an oder lässt sie durch?).
Warum müssen Sie überhaupt irgendetwas erledigen? Sollte der GC nicht für Sie referenzierte Ressourcen verwalten? Ah ... aber die Sprache versucht Ihnen Zugang zu System-Primitiven zu geben, die mit Nebenwirkungen arbeiten, mit expliziten Zuweisungen und Entnahmen. Sie müssen die zugewiesene Zuweisung aufheben (in allen Fällen) ... Sollten Sie nicht die faule Schnittstelle, die das System bereitstellt, an die Stelle von F # schieben, die in diesem Fall nur der Messenger ist?
Aber das scheint zu künstlich, es zeigt deutlich, dass "F # gegen Versuch / mit / endlich ist". Warum ist das so?
Ich denke, F # könnte überhaupt "gegen" Ausnahmebehandlung sein. Aus Gründen der .NET-Interoperabilität muss sie diese unterstützen, aber im Grunde gibt es keine Ausnahmeverarbeitung in der funktionalen Programmierung.
Throwing / Catching Exceptions bedeutet, "Sprünge ins Nirgendwo" zu vollziehen, die vom Typsystem nicht einmal bemerkt werden, was grundsätzlich gegen die Funktionsphilosophie verstößt.
Sie können rein funktionalen (monadischen) Code zum Umbrechen von Ausnahmen verwenden. Alle Fehler werden durch Werte behandelt, in Bezug auf das zugrundeliegende Typsystem und frei von Sprüngen / Nebeneffekten.
Anstatt eine Funktion zu schreiben
%Vor%das willkürliche Ausnahmen auslösen kann, geben Sie einfach
an %Vor%, wodurch dieser Punkt automatisch durch seine Typ-Signatur verdeutlicht wird.
* Das bedeutet nicht, dass wir keine Ausnahmesituationen behandeln, sondern nur die Art der Ausnahmebehandlung in .NET / C ++.
Tags und Links exception-handling f# exception