功能编程,递归游戏状态循环

时间:2012-08-22 09:44:19

标签: recursion functional-programming

我打算写一个简单的游戏来测试我对函数式编程的理解。执行主循环的功能方法是递归它,但是当生成越来越多的堆栈帧时,这不会占用内存吗?

由于

来自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))

2 个答案:

答案 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#例如在调试版本中没有这样做(但是在发布版本中)。项目设置中有一个复选框,可以在调试中启用。