Przeszukując od dawna, wciąż nie mogę znaleźć odpowiedzi. Z tego, co rozumiem, podczas uruchamiania F # 3.0 w .NET 4.5 nie będzie używana rekursja tylna dla metody rekursywnej, jeśli wywoływacz zawija połączenie w try/catch i/lub try/finally block. Jaka jest sytuacja, jeśli istnieje próba/catch lub próba/w końcu kilka poziomów na stosie?Rekurencja ogona i wyjątki w F #
Odpowiedz
Jeśli owinąć ciało jakiegoś (ogon) funkcji rekurencyjnej w try
... with
blok to funkcja nie jest już ogon rekurencyjne, ponieważ rama połączenie nie może zostać odrzucone podczas rekurencyjnego wywołania - musi pozostać w stos z zarejestrowaną obsługą wyjątku.
Na przykład, powiedzmy, że masz coś podobnego iter
funkcji dla List
:
let rec iter f list =
try
match list with
| [] ->()
| x::xs -> f x; iter f xs
with e ->
printfn "Failed: %s" e.Message
Po wywołaniu iter f [1;2;3]
następnie stworzy 4 zagnieżdżonych ramek stosu z obsługą wyjątków (a jeśli dodano rethrow
do with
oddziału, następnie wydrukowałby komunikat o błędzie 4 razy).
Naprawdę nie można dodawać procedur obsługi wyjątków bez łamania rekurencji ogona. Jednak zazwyczaj nie potrzebujesz zagnieżdżonych procedur obsługi wyjątków. Tak więc najlepszym rozwiązaniem jest przepisać funkcję tak, że nie trzeba obsłużyć wyjątki w każdym rekurencyjnego wywołania:
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
To ma trochę inne znaczenie - ale nie tworzyć zagnieżdżone obsługi wyjątków i loop
może być nadal w pełni rekurencyjny.
Inną opcją byłoby dodanie obsługi wyjątku tylko w stosunku do obiektu z wyłączeniem wywołania rekurencyjnego. Realistycznie, jedyną rzeczą, która może rzucić wyjątek w tym przykładzie jest połączenie z 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. Lenistwo i rekurencja ogona w Haskell, dlaczego to się zawiesza?
- 2. C: sprintf i rekurencja
- 3. Rekursja ogona w clojure
- 4. Wyjście `ogona -f` w końcu dokowanym CMD nie wykazujące
- 5. Eliminacja ogona w Mono
- 6. Jaki jest cel dodatkowego ldnull i ogona. w F # realizacji vs C#?
- 7. Rekursja ogona w R
- 8. Jak używać ogona w połączeniu z sed.
- 9. Jak określić "plasterek ogona" w Perlu?
- 10. F # zaawansowane ćwiczenia
- 11. Rekurencja i oczekiwanie/asynchronizacja Słowa kluczowe
- 12. Pętle zagnieżdżone schematu/Lispa i rekurencja
- 13. Dekoratory klas, dziedziczenie, super() i maksymalna rekurencja
- 14. Rekurencja perskiego dywanika
- 15. Rekurencja z wydajnością
- 16. async ctp rekurencja
- 17. Tworzenie rekurencji ogona w C++
- 18. Python: Wyjątki w zadaniach
- 19. Konstruktorzy i wyjątki Ruby
- 20. affectations i wyjątki
- 21. Wyjątki Akka Futures Wyjątki
- 22. Efektywność: rekurencja w stosunku do pętli
- 23. Common Lisp: Dlaczego funkcja rekurencji ogona powoduje przepełnienie stosu?
- 24. Jak działa rekurencja wewnątrz pętli
- 25. F # pętli w F #
- 26. F # F # interaktywne vs. roztworze i WCF
- 27. Jak nazywasz i organizujesz wyjątki?
- 28. Sprawdzone i niezaznaczone wyjątki w Javie
- 29. powolny kod bajtowy z ogona rekurencji
- 30. Dlaczego rekurencja rekina Scala jest szybsza niż pętla while?
Co się stanie, jeśli uruchomisz taką funkcję? –