[英]recursive stack overflow with exceptions in F#
让我们看看这段代码:
let rec doSomething () =
let d = GetSomeDataFromSomewhere()
match d with
| Some x -> x
| None -> doSomething()
所以这是某种形式的不间断轮询..
但现在是以下形式:
let rec doSomething () =
try
let d = GetSomeDataFromSomewhereButItCouldCrash()
match d with
| Some x -> x
| None -> doSomething()
with _ ->
doSomething()
如果有很多异常,那将导致堆栈溢出。
有人可以解释一下使这两个版本表现不同的机制吗?
问题是第二个版本中的第一个调用不在尾调用 position 中。这并不完全明显,因为递归调用是“function 所做的最后一件事”,但运行时仍然必须保留堆栈帧around,因为它需要保留关联的异常处理程序。
let rec doSomething () =
try
let d = GetSomeDataFromSomewhereButItCouldCrash()
match d with
| Some x -> x
| None -> doSomething() // This is not a tail call!
with _ ->
doSomething() // This is a tail call
如果您在调用GetSomeDataFromSomewhere
时直接处理异常并将它们变成None
,那么您可以保持相同的逻辑,但使其尾部递归:
let rec doSomething () =
let d = try GetSomeDataFromSomewhereButItCouldCrash() with _ -> None
match d with
| Some x -> x
| None -> doSomething()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.