scheme - 为什么方案中的所有实现都需要尾递归?

标签 scheme tail-recursion

尾递归更有效,因为它重用相同的堆栈帧而不是创建新的堆栈帧,但为什么方案中的所有内容都需要这样做?

最佳答案

Scheme 没有 goto,因此所有循环最终都是使用尾递归完成的。如果没有适当的尾递归保证,就没有可靠的方法在 Scheme 中提供循环。


更新:我想解释一下“最终使用尾递归”的意思。让我们看看 do 宏,因为@newacct 提到了它。例如:

(do ((i 1 (+ i 1)))
    ((> i 10))
  (display i)
  (newline))

正如我提到的,Scheme 没有 goto,因此它必须从某个地方获取它的循环。它实际上宏扩展为(类似于):

(let loop ((i 1))
  (unless (> i 10)
    (display i)
    (newline)
    (loop (+ i 1))))

注意这里的 loop 不是关键字或内置函数。它是由命名的 let 创建的命名函数,它在 unless 形式的底部被调用(通过尾递归) .

实际上,Scheme 中的所有标准循环形式都使用尾递归。无法摆脱它。


† 以下是名为 let(松散地说)的宏扩展为:

(letrec ((loop (lambda (i)
                 (unless (> i 10)
                   (display i)
                   (newline)
                   (loop (+ i 1))))))
  (loop 1))

‡ 严格来说,它宏扩展为:

((letrec ((loop (lambda (i)
                  (unless (> i 10)
                    (display i)
                    (newline)
                    (loop (+ i 1))))))
   loop)
 1)

关于scheme - 为什么方案中的所有实现都需要尾递归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14945240/

相关文章:

recursion - 带尾递归的慢字节码

haskell - 幂函数尾递归定义中严格评估的重要性

任何前两个数字的java斐波那契

scheme - 表达式简化

scheme - 类型的空列表不起作用的缺点

numbers - 如何计算Scheme中数字的位数之和?

c++ - 如果比较取决于返回值,是否可以进行尾递归?

functional-programming - 在 Scheme 中访问调用堆栈深度

duplicates - 如果多个字符在 Scheme 中彼此相邻,则从列表中删除它们

scheme - call/cc 是堆栈帧的副本还是执行中的实际跳转?