在下面的函数中,我尝试通过使用累加器来设置尾递归。但是,我遇到了堆栈溢出异常,这让我相信我设置函数的方式没有正确启用尾递归。
//F# attempting to make a tail recursive call via accumulator
let rec calc acc startNum =
match startNum with
| d when d = 1 -> List.rev (d::acc)
| e when e%2 = 0 -> calc (e::acc) (e/2)
| _ -> calc (startNum::acc) (startNum * 3 + 1)
据我了解,使用acc
将允许编译器看到不需要为每个递归调用保留所有堆栈帧,因为它可以将每次传递的结果填充到 acc 中并从每个帧返回。显然,我不明白如何正确使用累加器值,因此编译器会进行尾部调用。
Stephen Swensen 正确地指出,作为对问题的评论,如果您进行调试,VS 必须禁用尾部调用(否则它不会有堆栈帧跟随调用堆栈)。我knewVS 这样做了,但只是忘记了。
在了解了这个之后,我想知道运行时或编译器是否有可能抛出一个更好的异常,因为编译器知道您正在调试并且您编写了一个递归函数,在我看来,它可能会给你一个提示,例如
'Stack Overflow Exception: a recursive function does not
tail call by default when in debug mode'
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)