Scheme中的递归函数是否总是尾部调用优化?
我在Scheme中读过一些关于尾部调用优化的内容。但我不确定我是否理解尾部调用的概念。如果我有这样的代码:Scheme中的递归函数是否总是尾部调用优化?,scheme,tail-call-optimization,Scheme,Tail Call Optimization,我在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))))) 是否可以
(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)))))
是否可以对其进行优化,使其不会占用堆栈内存?
或者尾部调用优化只能应用于以下函数:
(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
调用函数时,您需要知道调用函数的位置,以便在调用完成后返回该位置,并在将来的计算中使用调用结果(afac
函数)
事实
的实现方式不同。事实
所做的最后一件事就是调用自身。不需要记住我们呼叫的地点-相反,我们可以执行尾部呼叫消除。在事实
返回后,不应执行任何其他操作。思考尾部调用的一个有用方法是询问“递归过程调用的结果必须发生什么?”
第一个函数不能进行尾部优化,因为必须使用对fac
的内部调用的结果,并乘以n
,以生成对fac
的整体调用的结果
然而,在第二种情况下,对fact
的“外部”调用的结果是。。。对fact
的内部调用的结果。无需对其执行任何其他操作,后一个值可以直接作为函数的值传回。这意味着不需要保留其他函数上下文,因此可以简单地丢弃它
R5RS标准通过使用a的概念来定义“尾部调用”,这基本上就是我上面描述的