【问题标题】:Is a recursive function in Scheme always tail-call optimized?Scheme 中的递归函数是否总是尾调用优化?
【发布时间】:2011-02-17 20:22:38
【问题描述】:

我在 Scheme 中读过一些关于尾调用优化的文章。但我不确定我是否理解尾调用的概念。如果我有这样的代码:

(define (fac n)
  (if (= n 0)
      1
      (* n (fac (- n 1)))))

这可以优化,使其不会占用堆栈内存吗? 还是只能将尾调用优化应用于这样的函数:

(define (factorial n)
    (let fact ([i n] [acc 1])
      (if (zero? i)
          acc
          (fact (- i 1) (* acc i)))))

【问题讨论】:

    标签: scheme tail-call-optimization


    【解决方案1】:

    考虑尾调用的一个有用方法是询问“递归过程调用的结果必须发生什么?”

    第一个函数不能进行尾部优化,因为必须使用内部调用fac结果,并乘以n以产生对@的整体调用的结果987654324@.

    然而,在第二种情况下,对fact 的“外部”调用的结果是......对fact 的内部调用的结果。不需要对它做任何其他事情,后一个值可以简单地作为函数的值直接传回。这意味着不必保留其他函数上下文,因此可以简单地将其丢弃。

    R5RS 标准通过使用 tail context 的概念定义“尾调用”,这基本上就是我上面所描述的。

    【讨论】:

      【解决方案2】:

      不,第一个fac 无法优化。

      调用函数时,您需要知道调用它的位置,以便在调用完成后返回该位置并在以后的计算中使用调用结果(fac 函数) .

      fact 的实现方式不同。 fact 做的最后一件事就是调用它自己。无需记住我们调用的位置——相反,我们可以执行尾调用消除。在fact 返回后,无需执行其他操作。

      【讨论】:

        猜你喜欢
        • 2017-04-18
        • 1970-01-01
        • 2015-12-10
        • 2012-11-15
        • 2011-09-04
        • 2018-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多