我打算写一个简单的游戏来测试我对函数式编程的理解。执行主循环的功能方法是递归它,但是当生成越来越多的堆栈帧时,这不会占用内存吗?
由于
来自How can you do anything useful without mutable state?
的示例// imperative version
pacman = new pacman(0, 0)
while true
if key = UP then pacman.y++
elif key = DOWN then pacman.y--
elif key = LEFT then pacman.x--
elif key = UP then pacman.x++
render(pacman)
// functional version
let rec loop pacman =
render(pacman)
let x, y = switch(key)
case LEFT: pacman.x - 1, pacman.y
case RIGHT: pacman.x + 1, pacman.y
case UP: pacman.x, pacman.y - 1
case DOWN: pacman.x, pacman.y + 1
loop(new pacman(x, y))
答案 0 :(得分:5)
您已使用tail recursion实施了loop
功能,即对loop
的递归调用是函数中的最后一项。这允许编译器/解释器(取决于语言)立即弹出当前堆栈帧并将其替换为递归调用的帧。
长话短说,你实现它的方式,没有堆栈溢出,loop
可以根据需要运行。
答案 1 :(得分:0)
递归是新的迭代:)博客插件:http://blogs.msdn.com/b/ashleyf/archive/2010/02/06/recursion-is-the-new-iteration.aspx
你说你正在使用Clojure,并且也热衷于了解F#。
事实证明,基于JVM的语言(Java,Scala,Clojure,...)不能支持VM级别的尾部调用优化,因此需要使用Clojure的recur
等变通方法。基于CLR的语言(F#,C#,VB,...)可以并且确实在IL中使用.tail
标记来导致早期丢弃堆栈帧。
尾调用优化会使调试变得很麻烦,所以F#例如在调试版本中没有这样做(但是在发布版本中)。项目设置中有一个复选框,可以在调试中启用。