5

还是val默认情况下 scala 对象中的 s 是惰性的?

无论如何,如果有必要val通过 using 在对象中声明 a lazy,是否可以执行类似的操作

lazy object SomeObject

或(就像你在 C++ 中所做的那样)

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

因为我想偷懒,不必重新标记我所有的valslazy val

4

4 回答 4

11

回答您的第一个问题(“ valscala 对象中的 s 默认情况下是惰性的吗?”):不,不完全是,但对象本身有点惰性,这可能已经足够惰性了。从Scala 语言规范的 5.4(“对象定义”)开始:

请注意,对象定义定义的值是惰性实例化的。构造new m$cls函数不是在对象定义时进行评估,而是m在程序执行期间第一次取消引用时进行评估(这可能永远不会)。

因此,例如,如果我们有这三个对象:

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

首先,对象已经被延迟初始化:

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 回答
1

简短的回答是:不,这是不可能的(除非你没有用宏做一些疯狂的运算)。

于 2012-08-11T18:14:53.007 回答
0

说到精神错乱(@om-nom-nom),也许可以调整Autoproxy 插件,使其创建惰性包装器。那将是……有趣。\

通常,Scala 编译器插件可以让您执行此操作。您可以通过标记特征或注释标记惰性对象,然后让编译器插件进行重写。编写编译器插件并不是最简单的事情,但它仍然很有趣。

于 2012-08-11T18:22:52.210 回答