Scala延迟val解释

Scala延迟val解释,scala,lazy-evaluation,Scala,Lazy Evaluation,我正在学习Scala的基础知识。我刚刚遇到了lazy val的概念。我有以下代码片段,可以在没有错误/警告的情况下工作 案例1 案例2 案例3 我了解案例1和案例2的工作原理。但是我不明白案例3中的代码是如何在没有错误/警告的情况下工作的。当b尚未定义时,Scala如何评估a的值 编辑 我没有在Scala REPL中运行此代码。我已将案例3中的代码保存在名为lazyVal.scala的文件中。我正在使用scala lazyVal.scala执行它。我认为scala解释了文件中的代码 如果我将la

我正在学习Scala的基础知识。我刚刚遇到了
lazy val
的概念。我有以下代码片段,可以在没有错误/警告的情况下工作

案例1 案例2 案例3 我了解案例1和案例2的工作原理。但是我不明白案例3中的代码是如何在没有错误/警告的情况下工作的。当
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版本
2.12.1
,如果这有什么区别的话。

构造函数中的语句按文本顺序执行,这就是为什么当
a
的初始化指代未初始化的
b
时会收到警告的原因。以一种你甚至没有得到警告的方式组成一个类是一个常见的错误。(有一个关于这方面的常见问题解答教程。)

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

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
                    ^
脚本运行程序按以下方式打包代码行:

object X {
  def main(args: Array[String]): Unit =
    new AnyRef {
      val a = 10 + b
      lazy val b = 5
      println(a)
    }
}
如果给它一个带有
main
或扩展
App
的对象,它不会包装代码,而是直接使用它


这三种配方之间有细微的差别。例如,顶级对象的构造函数作为静态初始值设定项运行;但是,
App
是一种特殊情况,它将初始化器代码作为
main
运行。(他们正在摆脱
应用程序
,因为它让人困惑。)

你只是按照这个顺序在REPL中尝试这些案例吗?如果是这样,则案例3中的
b
可能只是案例2中定义的最后一个
b
。否则,我将得到一个
错误:找不到:值b
。我投票将其作为非主题关闭,因为问题无法再现。@Alec请在问题编辑部分查看它。@Alec实际上,作为脚本问题,它更有趣,因为运行代码的每种方式的语义都不同。脚本运行程序将代码段包装在一个主函数中,在这里您可以看到与从REPL运行不同的错误和行为。更不用说作为应用程序运行了。请提供您在回答中提到的
常见问题解答教程的链接
?谢谢您提供的链接和答案。
object lazyVal extends App {
    val a = 10 + b
    lazy val b = 5
    println(a)
}
➜  Chapter1 scalac lazyVal.scala
➜  Chapter1 scala lazyVal
15
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
                    ^
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
object X {
  def main(args: Array[String]): Unit =
    new AnyRef {
      val a = 10 + b
      lazy val b = 5
      println(a)
    }
}