【问题标题】:Scala has smart compiler?Scala 有智能编译器吗?
【发布时间】:2011-11-13 22:08:46
【问题描述】:

我做了递归函数,就像

require : L (List[Int])

L 模式匹配

  1. Nil => Thread.dumpStack()
  2. x :: xs => print(x) + function(xs)
def function(L : List[Int]) {
    L match {
        case Nil => Thread.dumpStack()
        case x :: xs => print(x + " "); function(xs)
    }
}

val l = (1 to 5).toList // 函数(l)

所以我认为这个函数在栈帧n次,但是它出现了一次,我认为这个函数已经找到Nil并打印出异常Thread.dumpStack

scala 编译器是智能还是其他?

【问题讨论】:

  • -1 请更清楚:提供一个简短的代码示例和一个 REPL 成绩单来说明问题。

标签: exception scala


【解决方案1】:

您正在观察尾递归:从一次迭代到下一次迭代没有什么可存储的,因此编译器本质上将递归变成了一个while循环。 (所以,是的,编译器在这方面很聪明。)

【讨论】:

    【解决方案2】:

    正如 Rex Kerr 所指出的,这是应用尾调用优化的 Scala 编译器。如果你想知道最后编译了什么,你可以用一个额外的参数运行编译器:

    scalac -Xprint:tailcalls yourfile.scala
    

    这将在tailcalls 编译器阶段之后打印中间表示。 (如果您想了解所有阶段,也可以运行scalac -Xshow-phases。)例如,在以下输入上:

    object TailRec {
      def foo(l : List[Int]) : Unit = l match {
        case Nil => Thread.dumpStack()
        case x :: xs => println(x); foo(xs)
      }
    }
    

    编译器将打印(对于函数foo):

    def foo(l: List[Int]): Unit = {
      <synthetic> val _$this: TailRec.type = TailRec.this;
      _foo(_$this,l){
        l match {
          case immutable.this.Nil => java.this.lang.Thread.dumpStack()
          case (hd: Int, tl: List[Int])collection.immutable.::[Int]((x @ _), (xs @ _)) => {
            scala.this.Predef.println(x);
            _foo(TailRec.this, xs)
          }
        }
      }
    }
    

    _foo(_$this,l) 部分看起来像一个函数定义,但它实际上是一个标签,而“调用”_foo(TailRec.this, xs) 实际上是对那个标签的跳转。简而言之,编译器将递归调用重写为真正的 while 循环。

    编译器会在可能的情况下自动应用优化。如果你想确保一个函数被正确重写,你可以用@tailrec注解它,如果编译器不能优化它就会产生错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-03
      • 1970-01-01
      • 2022-08-04
      • 2019-03-18
      • 1970-01-01
      相关资源
      最近更新 更多