Scala 函数字面量中的变量定义

Variable definition in Scala function literal

我想知道这段代码的结果

object localTest {
  def hello = {
    var t = 3
    () => {
      t = t + 3
      println(t)
    }
  }
}
object mainObj {
  def main(args: Array[String]): Unit = {
    val test = localTest.hello
    while (true) {
      Thread.sleep(1000)
      test()
    }
  }
}

为什么hello函数中的变量t只赋值一次,结果就是6,9,12....

我猜这可能与闭包属性有关,但为什么var t = 3只执行了一次?

这不是通常的函数式 Scala 代码,其中不可变和 val 优先于可变性。这种风格让我想起了 Javascript,像这样的事情经常出现。是的,你没看错,这跟闭包有关:

  • hello 方法定义了一个范围。在这个作用域中存在两个东西:t 变量和 lambda(函数文字 () => {...}
  • lambda 被 return 编辑为 hello 方法中的 return 值,分配到 test 变量中并由 while 重复执行循环
  • lambda 正在更改 t 变量,该变量被捕获在其中。

该变量存在于hello的范围内,但由于它被lambda捕获,是否是反复使用的同一个变量。它不是从 while 循环中执行的 hello 作用域,而是 lambda 主体。 hello 仅执行一次以创建 t 变量和 lambda。

扩展 hello 定义可能有助于您更轻松地理解这一点:

val test = {
  var t = 3
  () => {
    t = t + 3
    println(t)
  }
}
while (true) {
  Thread.sleep(1000)
  test()
}

这可以转换为具有相同功能的以下代码,只是 t 范围将被扩展,以便即使 lambda 以外的代码也可以看到它:

var t = 3
val test = () => {
    t = t + 3
    println(t)
  }
while (true) {
  Thread.sleep(1000)
  test()
}