Clojure不会单独执行尾部调用优化:当您具有尾部递归函数并且想要对其进行优化时,必须使用特殊形式recur
。同样,如果您有两个相互递归的函数,则只能使用来优化它们trampoline
。
Scala编译器能够为递归函数执行TCO,但不能为两个相互递归函数执行TCO。
每当我阅读这些限制时,它们总是归因于JVM模型固有的某些限制。我对编译器一无所知,但这使我有些困惑。让我举一个例子Programming Scala
。这里的功能
def approximate(guess: Double): Double =
if (isGoodEnough(guess)) guess
else approximate(improve(guess))
被翻译成
0: aload_0
1: astore_3
2: aload_0
3: dload_1
4: invokevirtual #24; //Method isGoodEnough:(D)Z
7: ifeq
10: dload_1
11: dreturn
12: aload_0
13: dload_1
14: invokevirtual #27; //Method improve:(D)D
17: dstore_1
18: goto 2
因此,在字节码级别,只需要一个goto
。实际上,在这种情况下,繁琐的工作由编译器完成。
基础虚拟机的什么功能将使编译器更轻松地处理TCO?
附带说明一下,我不希望实际的计算机比JVM更智能。尽管如此,许多编译为本机代码的语言(例如Haskell)似乎在优化尾调用方面没有问题(嗯,Haskell有时可能由于懒惰而遇到问题,但这是另一个问题)。