[英]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.