【问题标题】:Understanding the Idea behind Tail Recursion in Scala理解 Scala 中尾递归背后的思想
【发布时间】:2017-12-31 16:05:24
【问题描述】:

我来自面向对象的背景,主要用 Java 编写应用程序。我最近开始在 Scala 上进行更多探索,并且一直在阅读一些文本。因此,我遇到了一种叫做尾递归的东西。我了解如何编写尾递归方法。

例如 - 将元素添加到 List 中(当然这可以使用 reduce 方法完成)但是为了理解起见,我写了一个尾递归方法:

@scala.annotation.tailrec
def sum(l: List[Int], acc: Int): Int = l match {
  case Nil => acc
  case x :: xs => sum(xs, acc + x)
}

Scala 运行时如何在内部处理这种递归?

【问题讨论】:

    标签: scala recursion


    【解决方案1】:

    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 循环。

    【讨论】:

      猜你喜欢
      • 2018-03-17
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      相关资源
      最近更新 更多