Scala函数文字中的变量定义

时间:2018-11-12 07:25:05

标签: scala closures 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()
    }
  }
}

为什么t函数中的变量hello只分配一次,结果将是6、9、12 ...

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

1 个答案:

答案 0 :(得分:2)

这不是通常的功能性Scala代码,在该代码中,不可变和val优先于可变性。这种风格让我想起了Javascript,在Javascript中,这种情况经常出现。是的,您是正确的,这与关闭有关:

  • hello方法定义范围。在此范围内,存在两件事:t变量和lambda(函数文字() => {...}
  • lambda作为返回值从hello方法返回,分配给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()
}