5

またはval、scalaオブジェクトのsはデフォルトで怠惰ですか?

valとにかく、を使用して怠惰なオブジェクトでを宣言する必要がある場合、次のlazyようなことを行うことは可能ですか?

lazy object SomeObject

または(C ++で行うように)

object A {
lazy:
    val a
    val b
    ...
}

怠惰になりたいので、すべてvalのラベルを変更する必要はありませんlazy val

4

4 に答える 4

11

最初の質問に答えるには(「valデフォルトでscalaオブジェクトのsは怠惰ですか?」):いいえ、正確ではありませんが、オブジェクト自体は一種の怠惰であり、十分に怠惰である可能性があります。Scala言語仕様の5.4(「オブジェクト定義」)から:

オブジェクト定義によって定義された値は遅延してインスタンス化されることに注意してください。コンストラクターは、new m$clsオブジェクト定義の時点では評価されませんが、代わりmに、プログラムの実行中に最初に逆参照されるときに評価されます(これはまったく行われない可能性があります)。

したがって、たとえば、次の3つのオブジェクトがある場合:

object X {
  val answer = { println("Here's X's answer!"); 42 }
}

object Y {
  lazy val answer = { println("Here's Y's answer!"); 1 }
}

object Z extends App {
  println("Here we go.")
  println(X)
  println(Y)
  println(X.answer)
  println(Y.answer)
}

次に、を実行するZと、次のように表示されます。

Here we go.
Here's X's answer!
X$@38d24866
Y$@f1aa6ce
42
Here's Y's answer!
1

したがって、valinXは怠惰ではありませんが、初めて使用するまで評価されませんX

于 2012-08-11T19:27:18.183 に答える
1

簡単な答えは次のとおりです。いいえ、それは不可能です(マクロで非常識なクランチを行っていない場合を除く)。

于 2012-08-11T18:14:53.007 に答える
1

まず第一に、オブジェクトはすでに怠惰に初期化されています:

object Y {
  println("aqui")
  val a = 0
}

Y.a  // runs body of Y

次に、複数のsが一度valに遅延初期化されることに満足している場合は、タプルからのパターン抽出を使用できます。

object X {
  val a = 0
  lazy val (b, c) = {
    println("aqui")
    (1, "hallo")
  }
}

X.a  // runs body of X, initialises strict vals
X.b  // initialises both b and c
X.c
于 2012-08-11T23:03:52.057 に答える
0

狂気(@ om-nom-nom)と言えば、怠惰なラッパーを作成するようにAutoproxyプラグインを適応させることが可能かもしれません。それは...面白いでしょう。\

一般に、Scalaコンパイラプラグインを使用するとこれを実行できます。マーカー特性または注釈を介して遅延オブジェクトにタグを付けてから、コンパイラプラグインに書き換えを行わせることができます。コンパイラプラグインを作成するのは簡単なことではありませんが、それでも楽しい場合があります。

于 2012-08-11T18:22:52.210 に答える