2011-08-05 29 views
12

次は両方の整数のストリームを作成するためのものです:最初は結構ですストリームはいつ遅延する必要がありますか?

val s: Stream[Int] = 1 #:: s.map(_ + 1) 

def makeStream = { 
    val s: Stream[Int] = 1 #:: s.map(_ + 1) 
    s 
} 

を。しかしmakeStream方法はコンパイルされません。

error: forward reference extends over definition of value s 
    val s: Stream[Int] = 1 #:: s.map(_ + 1) 
          ^

我々はslazy valを作る場合にのみコンパイルされます。メソッド内でlazy valにする必要があるのはなぜですか?外部ではありません。

答えて

16

クラス内で、val定義は、非表示のクラスフィールドを参照する「ゲッター」メソッドに逆コンパイルします。これらの「getter」メソッドは、Javaメソッドのセマンティクスであるため、自己参照型(または、クラス初期化子が「getter」を参照できます)にすることができます。 val sの "外部"定義は実際にはREPLによって隠されたクラスにラップされていることに注意してください(これは、REPLがvalをトップレベルで宣言できないという制限を回避する方法です)。

メソッド内では、valの定義は「ゲッター」メソッドに逆コンパイルされず、スタックに値を生成するために必要なバイトコードにデコンパイルされます。他方、lazy valは、常に、自己参照可能な「ゲッター」法を常に必要とする。

関連する問題