代码之家  ›  专栏  ›  技术社区  ›  Varun Risbud

Scala lazy val解释

  •  3
  • Varun Risbud  · 技术社区  · 8 年前

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

    案例1

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

    案例2

    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 正在工作,没有错误/警告。Scala如何评估 a b 尚未定义?

    我没有在中运行此代码 Scala REPL .我已将案例3中的代码保存在名为 lazyVal.scala scala lazyVal.scala 。我认为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 version 2.12.1 如果这有什么不同的话。

    1 回复  |  直到 5 年前
        1
  •  5
  •   som-snytt    8 年前

    构造函数中的语句按文本顺序执行,这就是为什么在初始化 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
                        ^
    

    在施工期间进行评估。

    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)
        }
    }
    

    main 或是延伸 App ,它不会包装代码,而是直接使用它。

    这三种配方之间存在细微差异。例如,顶级对象的构造函数作为静态初始值设定项运行;但是一个 特殊情况下运行初始化器代码为 应用程序 因为这让人困惑。)

    推荐文章