【发布时间】:2014-06-04 05:20:49
【问题描述】:
据说某些 VM(尤其是 JVM)不支持 TCO。因此,像 Clojure 这样的语言要求用户改用 loop recur。
但是,我可以重写自尾调用以使用循环。例如,这是一个尾调用阶乘:
def factorial(x, accum):
if x == 1:
return accum
else:
return factorial(x - 1, accum * x)
这是一个等效的循环:
def factorial(x, accum):
while True:
if x == 1:
return accum
else:
x = x - 1
accum = accum * x
这可以由编译器完成(我已经编写了执行此操作的宏)。对于相互递归,您可以简单地内联您正在调用的函数。
既然您可以在不需要任何 VM 的情况下实现 TCO,为什么语言(例如 Clojure、Armed Bear Common Lisp)不这样做呢?我错过了什么?
【问题讨论】:
-
请注意,TCO 并非专门针对自递归调用。这只是一个特例。
-
是的。但是要么你调用同一个函数(你可以写成一个循环),要么你正在调用另一个函数(你可以内联)。我相信这两种技术结合在一起是一个通用的解决方案。
-
内联是没有办法的。
-
能否简单内联 Clojure 中的函数调用?我见过的案例将一个(希望是对应的)宏作为元数据附加到
defn。 -
您说的是尾递归最简单的形式。现在考虑尾调用一个虚方法。你不一定知道你在调用哪个函数。
标签: clojure lisp tail-recursion tail-call-optimization