繁体   English   中英

scala Closure自由变量

[英]scala Closure Free variable

val m1 = 99

val g = (_:Int) + m1

g(10)  // returns 109

val m1 = 88

g(10)  // returns 109

var n1 = 99

val h = (_:Int) + n1

h(10)  // returns 109

n1 = 88

h(10)  // returns  98

var n1 = 66

h(10)  // returns 98

有人可以向我解释这是如何工作的吗? 为什么闭包不跟踪“自由变量”的变化?

下面的代码是用Scala编程编写的,但我发现很难将它链接到上面的场景:

Scala的闭包本身捕获变量,而不是变量引用的值。

这看起来像一个REPL会话。 每次引入val m1var n1 ,都会隐藏具有相同名称的变量的先前定义。 阴影适用于此后发送到REPL的新行。 但是已编译的行仍然引用旧变量。

通过重命名变量可以很容易地解释上述行为,从而不会发生阴影:每次重新声明某些内容时都会引入新名称。 这会产生:

val m1 = 99

val g = (_:Int) + m1

g(10)  // returns 109

val m2 = 88

g(10)  // returns 109

-

var n1 = 99

val h = (_:Int) + n1

h(10)  // returns 109

n1 = 88

h(10)  // returns  98

var n2 = 66

h(10)  // returns 98

在这两种情况下, gh的定义仍然分别指m1 / n1 valvar的定义是无关紧要的。

但是,赋值n1 = 88不会引入新变量。 它会更改现有变量n1的值。 在这种情况下, h看到更新的n1值。

我假设您正在尝试在REPL中执行此操作。 当你做val m1 =var n1 = 第二次时你的解释很简单 - 你只是做了一个新的定义(你可能会认为它是m1_2 / n1_2 ),这与你以前的定义无关(以任何方式)定义m1 / n1 你的hg对这个先前定义的值/变量是封闭的,不管它们是否被新的阴影所影响。

PS你不能在REPL之外做这个技巧(例如在类定义上)

您在REPL中所做的与此类似

object Test extends App{
  val m1 = 99

  val g = (_: Int) + m1

  println(g(10))   // returns 109

  {
    val m1 = 88    // creates a new variable that shadows m1
    println(g(10)) // returns 109
  }
}

您有两个名为m1变量。 g的定义仅使用第一个。

这是因为您正在使用Repl,它将您的语句封装到单个对象中,然后在后续使用时导入它们。 因此,您正在目睹的特殊行为。

请参阅https://stackoverflow.com/a/22773553/2509908

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM