Scala 运行时如何在内部处理这种递归?
不是。它在编译时由编译器处理。
尾递归等效于while 循环。因此,尾递归方法可以编译为while 循环,或者更准确地说,它可以以与while 循环相同的方式进行编译。当然,如何准确地编译它取决于所使用的编译器。
目前有 Scala 的三种主要实现,它们是 Scala-native(一种针对具有自己的运行时的本机机器代码的编译器)、Scala.js(一种针对 ECMAScript 平台的编译器,位于 ECMAScript 运行时之上),以及 JVM 实现 Scala,它也被称为“Scala”,就像语言一样(它针对 JVM 平台并使用 JVM 运行时)。曾经有一个 Scala.NET,但不再积极维护。
我将在这个答案中关注 Scala-JVM。
我将使用与您的示例略有不同的示例,因为模式匹配的编码实际上相当复杂。让我们从最简单的尾递归函数开始:
def foo(): Unit = foo()
Scala-JVM 将其编译为以下 JVM 字节码:
public void foo()
0: goto 0
还记得我上面说过尾递归等同于循环吗?好吧,JVM 没有循环,它只有GOTO。这与while 循环完全相同:
def bar(): Unit = while (true) {}
编译成:
public void bar()
0: goto 0
还有一个更有趣的例子:
def baz(n: Int): Int = if (n <= 0) n else baz(n-1)
编译为:
public int baz(int);
0: iload_1
1: iconst_0
2: if_icmpgt 9
5: iload_1
6: goto 16
9: iload_1
10: iconst_1
11: isub
12: istore_1
13: goto 0
16: ireturn
如您所见,它只是一个while 循环。