Ich habe seit Ewigkeiten googeln und kann immer noch nicht die Antwort finden. Von dem, was ich F # 3.0 runnning auf .NET 4.5 nicht Endrekursion für eine rekursive Methode verwenden, wenn der Aufrufer den Anruf in einer try/catch gewickelt hat und/oder try/finally-Block zu verstehen. Wie ist die Situation, wenn es einen Versuch/Fang gibt oder versuchsweise/schließlich ein paar Stufen höher ist?Endrekursion und Ausnahmen in F #
Antwort
Wenn Sie den Körper von einigen (Schwanz) rekursive Funktion in einem try
wickeln ... with
Block dann ist die Funktion rekursiv nicht mehr Schwanz, weil der Anruf Rahmen nicht während der rekursiven Aufruf verworfen werden kann - es muss in bleiben der Stapel mit einem registrierten Ausnahmebehandler.
Zum Beispiel, sagen Sie so etwas wie iter
Funktion für List
haben:
let rec iter f list =
try
match list with
| [] ->()
| x::xs -> f x; iter f xs
with e ->
printfn "Failed: %s" e.Message
Wenn Sie iter f [1;2;3]
dann nennen es 4 verschachtelt Stack-Frames mit Exception-Handler erstellen wird (und wenn Sie rethrow
in die with
Zweig hinzugefügt, dann würde es tatsächlich die Fehlermeldung 4 mal drucken).
Sie können nicht wirklich Exception-Handler, ohne zu brechen Schwanz-Rekursion hinzufügen. Normalerweise benötigen Sie jedoch verschachtelte Ausnahmehandler nicht. So ist die beste Lösung ist es, die Funktion neu zu schreiben, so dass es keine Ausnahmen in jedem rekursiven Aufruf behandeln muss:
let iter f list =
let rec loop list =
match list with
| [] ->()
| x::xs -> f x; loop xs
try loop list
with e -> printfn "Failed: %s" e.Message
Das hat etwas andere Bedeutung - aber es erzeugt keine verschachtelte Handler Ausnahme und loop
kann immer noch sein, vollständig tail rekursiv.
Eine andere Option wäre, Ausnahmebehandlung nur über den Körper außer der Tail-rekursive Aufruf hinzuzufügen. Realistisch gesehen, das einzige, was eine Ausnahme in diesem Beispiel werfen kann, ist der Aufruf von f
;
let rec iter f list =
match list with
| [] ->()
| x::xs ->
try
f x
with e ->
printfn "Failed: %s" e.Message
iter f xs
- 1. Does F # tun TCO (Endrekursion Optimierung) mit |> Option.bind
- 2. langsamen Bytecode mit Endrekursion
- 3. Wie ignoriere ich Ausnahmen in F #
- 4. F # asynchrone Webanforderung, die Ausnahmen behandelt
- 5. Endrekursion vs Kopf klassischen Rekursion
- 6. F # und ADO.NET - idiomatische F #
- 7. Kotlin: Endrekursion für beide Seiten rekursiven Funktionen
- 8. Benutzerdefiniert und eingebaut Argumente in Ausnahmen
- 9. F # Endlosschleifen in F #
- 10. Fortran: Unterschied zwischen f und F extension
- 11. Ereignisse und Delegaten in F #
- 12. Global.asax und unbehandelte Ausnahmen
- 13. RMI und Ausnahmen
- 14. Visual Studio und Ausnahmen
- 15. Prozesszusammensetzung und Ausnahmen
- 16. konvertieren amp; auf & und? F Grad F in Vb.net
- 17. WCF Fehler und Ausnahmen
- 18. Behinderte Ausnahmen und noexcept()
- 19. Java-Rekursion und Ausnahmen
- 20. Ausnahmen und Operatorüberlastung
- 21. Statischer Konstruktor und Ausnahmen
- 22. MailboxProcessor und Ausnahmen
- 23. Ausnahmen in Konstruktoren
- 24. F # und Fuzzy Logic
- 25. F # -Codierstil und -Standard
- 26. C++ - Ausnahmen, GCC und "Inline-Funktionen" Flag
- 27. F # Schnittstellen und Eigenschaften
- 28. F # und PLINQ Erweiterungsmethoden
- 29. F # und Namespace
- 30. F # und op_GreaterThan
Was passiert, wenn Sie eine solche Funktion ausführen? –