Scheme中的递归函数是否总是尾调用优化?

我已经阅读了一些关于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)))))
    
已邀请:
考虑尾调用的一种有用方法是询问“递归过程调用的结果必然会发生什么?” 第一个函数不能进行尾部优化,因为必须使用内部调用
fac
的结果,并乘以
n
以产生整体调用的结果
fac
。 然而,在第二种情况下,对“ѭ5”的“外部”调用的结果是......内部调用“ѭ5”的结果。没有必要对它进行任何操作,后一个值可以直接作为函数的值传回。这意味着不必保留其他函数上下文,因此可以简单地将其丢弃。 R5RS标准通过使用尾部上下文的概念来定义“尾部调用”,这基本上就是我上面所描述的。     
不,第一个
fac
无法优化。 调用函数时,您需要知道调用它的位置,以便在调用完成后返回到该位置,并在将来的计算中使用调用的结果(a
fac
函数)。
fact
的实现方式不同。
fact
做的最后一件事就是自称。没有必要记住我们正在调用的地方 - 相反,我们可以执行尾部调用消除。在
fact
返回后,没有其他动作应该完成。     

要回复问题请先登录注册