[英]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 m1
或var 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
在这两种情况下, g
和h
的定义仍然分别指m1
/ n1
。 新val
和var
的定义是无关紧要的。
但是,赋值n1 = 88
不会引入新变量。 它会更改现有变量n1
的值。 在这种情况下, h
看到更新的n1
值。
我假设您正在尝试在REPL中执行此操作。 当你做val m1 =
或var n1 =
第二次时你的解释很简单 - 你只是做了一个新的定义(你可能会认为它是m1_2
/ n1_2
),这与你以前的定义无关(以任何方式)定义m1
/ n1
。 你的h
和g
对这个先前定义的值/变量是封闭的,不管它们是否被新的阴影所影响。
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,它将您的语句封装到单个对象中,然后在后续使用时导入它们。 因此,您正在目睹的特殊行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.