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

Moe*_*Moe 5 scheme tail-call-optimization

我已经阅读了一些关于Scheme中尾调优化的内容.但我不确定我是否理解尾调用的概念.如果我有这样的代码:

(define (fac n)
  (if (= n 0)
      1
      (* n (fac (- n 1)))))
Run Code Online (Sandbox Code Playgroud)

这可以优化,以便它不会占用堆栈内存吗?或者尾部调用优化只能应用于这样的函数:

(define (factorial n)
    (let fact ([i n] [acc 1])
      (if (zero? i)
          acc
          (fact (- i 1) (* acc i)))))
Run Code Online (Sandbox Code Playgroud)

Nor*_*ray 10

考虑尾调用的一种有用方法是询问"递归过程调用的结果必然会发生什么?"

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

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

R5RS标准通过使用尾部上下文的概念来定义"尾部调用" ,这基本上就是我上面所描述的.