2011-11-12 11 views
4

私はヴァル・L =(1〜5)Scalaにはスマートコンパイラがありますか?

  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) 
    } 
} 

に一致

require : L (List[Int]) 

Lのパターンと同様に、再帰関数を作りました。 toList // 機能(L)

だから私は、スタックフレームn回でこの機能をと思うが、それは1回発生し、私はこの機能が既にNilを見つけ、例外Thread.dumpStackをプリントアウトしていると思います。

スカラーコンパイラはスマートですか他のですか?

+0

-1明確にしてください:質問を説明するために、短いコードサンプルとREPLのトランスクリプトを提供してください。 – retronym

答えて

7

テール再帰:1つの反復から次の反復までは何も格納されないため、コンパイラによって本質的にwhileループに変わります。 (そう、コンパイラはそのようにスマートです。)

+0

Aha、Tail再帰。 :) – Silvester

1

Rex Kerrは、tail呼び出し最適化を適用した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と注釈を付けることができます。最適化できない場合、コンパイラはエラーを生成します。

関連する問題