Scala有智能编译器吗?

时间:2011-11-12 13:01:49

标签: exception scala

我做了递归函数,就像

一样
require : L (List[Int])

L模式匹配

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

    val l =(1到5).toList //   功能(l)

    所以我认为这个函数在堆栈框架中有n次,但它发生了一次,我认为这个函数已经找到Nil并打印出异常Thread.dumpStack

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

2 个答案:

答案 0 :(得分:7)

您正在观察尾递归:从一次迭代到下一次迭代没有任何内容存储,因此递归基本上由编译器转换为while循环。 (所以,是的,编译器很聪明。)

答案 1 :(得分:1)

正如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)看起来像一个函数定义,但它实际上是一个标签,而“call”_foo(TailRec.this, xs)实际上是跳转到该标签。简而言之,编译器将递归调用重写为真正的while循环。

编译器会尽可能自动应用优化。如果要确保正确地重写函数,可以使用@tailrec对其进行注释,如果无法对其进行优化,编译器将产生错误。