我有一个简单的游戏循环实现
let gameLoop gamestate =
let rec innerLoop prev gamestate =
let now = getTicks()
let delta = now - prev
gamestate
|> readInput delta
|> update delta
|> render delta
|> innerLoop delta
innerLoop 0L gamestate
此实现会引发 stackoverflow 异常。在我看来这应该是尾递归。我可以这样解决
let gameLoop gamestate =
let rec innerLoop prev gamestate =
let now = getTicks()
let delta = now - prev
let newState = gamestate
|> readInput delta
|> update delta
|> render delta
innerLoop now newState
innerLoop 0L gamestate
所以我的问题是为什么第一个代码示例会抛出 stackoverflow 异常。
我认为答案与线程中的相同Vandroiy https://stackoverflow.com/users/4191347/vandroiy链接:当你有
a
|> f b
然后在调试模式下,编译器可能会像字面解释一样编译它
(f b) a
并明确计算f b
一步一步将其应用到a
在第二步中。带参数的调用a
仍然是尾调用,但如果编译器不发出tail.
操作码前缀(因为尾部调用被关闭,因为它们默认处于调试模式),那么您将通过显式调用增加堆栈并最终导致堆栈溢出。
另一方面,如果你写
f b a
直接那么这不会发生:编译器不会部分应用f
,并且会认识到这是一个直接递归调用并将其优化为循环(即使在调试模式下)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)