簡體   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