简体   繁体   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

Can someone explain to me how this works? 有人可以向我解释这是如何工作的吗? Why is closure not tracking the changes in "free variable"? 为什么闭包不跟踪“自由变量”的变化?

The line below is written in Programming in Scala ,but i am finding it difficult to link it to above scenario : 下面的代码是用Scala编程编写的,但我发现很难将它链接到上面的场景:

Scala's closures capture variables themselves, not the value to which variables refer. Scala的闭包本身捕获变量,而不是变量引用的值。

This looks like a REPL session. 这看起来像一个REPL会话。 Every time you introduce val m1 or var n1 , you shadow the previous definition of a variable with the same name. 每次引入val m1var n1 ,都会隐藏具有相同名称的变量的先前定义。 The shadowing applies to new lines sent to the REPL after that. 阴影适用于此后发送到REPL的新行。 But lines already compiled still refer to the old variable. 但是已编译的行仍然引用旧变量。

It is easy to explain the above behavior by renaming variables so that no shadowing occurs: introduce new names every time you redeclare something. 通过重命名变量可以很容易地解释上述行为,从而不会发生阴影:每次重新声明某些内容时都会引入新名称。 This yields: 这会产生:

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

In both cases, the definitions of g and h still refer to m1 / n1 respectively. 在这两种情况下, gh的定义仍然分别指m1 / n1 The definition of new val s and var s is irrelevant. valvar的定义是无关紧要的。

However, the assignment n1 = 88 does not introduce a new variable. 但是,赋值n1 = 88不会引入新变量。 It changes the value of the existing variable n1 . 它会更改现有变量n1的值。 In that case, h sees the updated value of n1 . 在这种情况下, h看到更新的n1值。

I assume you're trying to do it inside REPL. 我假设您正在尝试在REPL中执行此操作。 The explanation is simple when you do either val m1 = or var n1 = second time - you're just making a new definition (you may think of it as m1_2 / n1_2 ), which is not related (in any way) to your previously defined m1 / n1 . 当你做val m1 =var n1 = 第二次时你的解释很简单 - 你只是做了一个新的定义(你可能会认为它是m1_2 / n1_2 ),这与你以前的定义无关(以任何方式)定义m1 / n1 Your h and g are closed to this previously defined values/variables, regardless that they shadowed by new. 你的hg对这个先前定义的值/变量是封闭的,不管它们是否被新的阴影所影响。

PS You can't do this trick outside of REPL (on class definition for example) PS你不能在REPL之外做这个技巧(例如在类定义上)

What you are doing in the REPL is similar to 您在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
  }
}

You have two variables named m1 . 您有两个名为m1变量。 The definition of g uses only the first one. g的定义仅使用第一个。

That's because you are using the Repl, which encloses your statements into individual objects and then imports them on subsequent usage. 这是因为您正在使用Repl,它将您的语句封装到单个对象中,然后在后续使用时导入它们。 Hence the peculiar behaviour you are witnessing. 因此,您正在目睹的特殊行为。

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

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

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