Scala lazy val 解释

Scala lazy val interpretation

我正在学习 Scala 基础知识。我刚刚遇到 lazy val 概念。我有以下代码片段,无需 errors/warnings

案例一

lazy val a = 10 + b
lazy val b = 5
println(a)

案例二

lazy val a = 10 + b
val b = 5
println(a)

案例三

val a = 10 + b
lazy val b = 5
println(a)

我了解 case 1 & 2 的工作原理。但是我不明白 case 3 中的代码在没有 error/warning 的情况下是如何工作的。当 b 尚未定义时,Scala 如何计算 a 的值?

编辑

我不是运行这个代码在Scala REPL。我已将案例 3 中的代码保存在名为 lazyVal.scala 的文件中。我正在使用 scala lazyVal.scala 执行它。我认为 scala 会解释文件中的代码。

如果我将 lazyVal.scala 中的代码更改为

val a = 10 + b
val b = 5
println(a)

并使用 scala lazyVal.scala 执行它 我收到警告

/Users/varun.risbud/scalaRepo/src/Chapter1/lazyVal.scala:1: warning: Reference to uninitialized value b
val a = 10 + b
         ^
one warning found
10

此外,如果我更改代码以创建对象并扩展应用程序,它就可以工作

object lazyVal extends App {
    val a = 10 + b
    lazy val b = 5
    println(a)
}
➜  Chapter1 scalac lazyVal.scala
➜  Chapter1 scala lazyVal
15

我的 scala version2.12.1 如果这有什么不同的话。

构造函数中的语句按文本顺序执行,这就是为什么当 a 的初始化引用未初始化的 b 时会收到警告。以一种您甚至没有收到警告的方式编写 class 是一个常见的错误。 (有一个常见问题解答教程。)

在本地语句序列中禁止使用相同的文本:

scala> :pa
// Entering paste mode (ctrl-D to finish)

locally {
val a = 10 + b
lazy val b = 5
println(a)
}

// Exiting paste mode, now interpreting.

<console>:13: error: forward reference extends over definition of value a
       val a = 10 + b
                    ^

作为 class 或对象的成员,惰性成员被计算 "on demand",而 a 在构造期间被计算。

scala> :pa
// Entering paste mode (ctrl-D to finish)

object X {
val a = 10 + b
lazy val b = 5
println(a)
}

// Exiting paste mode, now interpreting.

defined object X

scala> X
15
res1: X.type = X$@6a9344f5

脚本 运行ner 以这种方式打包您的代码行:

object X {
  def main(args: Array[String]): Unit =
    new AnyRef {
      val a = 10 + b
      lazy val b = 5
      println(a)
    }
}

如果你给它一个带有 main 或扩展 App 的对象,它不会包装代码,而是直接使用它。

三种配方之间存在细微差别。例如,顶层对象的构造函数是 运行 作为静态初始化器;但是 App 是 运行 初始化代码的特殊情况,如 main。 (他们正在摆脱 App 因为它令人困惑。)