2014-10-20 60 views
4

我正在閱讀Scala編程第二版(這本書很棒,比scala的網站更好地以非火箭科學的方式解釋事物)以及當我經過不可變和可變集時,我注意到了這個怪事。Scala不可變集在聲明爲變量時是可變的

它聲明以下作爲一個不可變組

var jetSet=Set("Boeing", "Airbus") 
jetSet+="Lear" 
println(jetSet.contains("Cessna")) 

然後指出,只有可變的集定義+ =方法。好吧,這是非常有道理的。問題是這個代碼有效。而在REPL中測試時創建的集合的類型實際上是不可變的集合,但它具有定義的+ =方法,並且它的功能非常好。看哪

scala> var a = Set("Adam", "Bill") 
a: scala.collection.immutable.Set[String] = Set(Adam, Bill) 

scala> a += "Colleen" 

scala> println(a) 
Set(Adam, Bill, Colleen) 

scala> a.getClass 
res8: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set3 

但如果我宣佈設定爲VAL,不可改變集創建不具備+ =方法定義

scala> val b = Set("Adam", "Bill") 
b: scala.collection.immutable.Set[String] = Set(Adam, Bill) 

scala> b += "Colleen" 
<console>:9: error: value += is not a member of scala.collection.immutable.Set[String] 
      b += "Colleen" 

這到底是怎麼回事?它們都被聲明爲一個不可變的Set,但聲明爲var的那個可以訪問+ =方法並可以使用它。

此外,當我不停地打電話對VAR不可變set我發現了一些奇怪的方法的getClass ....

scala> a.getClass 
res10: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set3 

scala> a += "One" 

scala> a.getClass 
res12: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set4 

scala> a += "Two" 

scala> a.getClass 
res14: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.HashSet$HashTrieSet 

scala> a += "Tree" 

scala> a.getClass 
res16: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.HashSet$HashTrieSet 

scala> a 
res17: scala.collection.immutable.Set[String] = Set(One, Tree, Bill, Adam, Two, Colleen) 

我的猜測是,由於一些隱藏的語法糖,斯卡拉認識到這是一個變數和無論如何你都可以用新構建的集合替換它。

+1

'Set'是不可變的,但是'a'是可變的,向該集合中添加一個元素將創建一個新集合,並將結果賦給'a',如果'a'是一個val,則它是不可變的,而您不能重新分配給它。 – 2014-10-20 15:31:04

回答

12

什麼是可變的不是Set,是它的參考。

a += "Colleen" 

返回一個新的不可變集,分配給可變變量a

Scala中執行語法變換,把表達成

a = a + "Colleen" 

在殼體+=沒有定義(如在不可變的情況下Set

顯然+=沒有意義時aval,因爲您不能重新分配它,因此被禁止。

下面是編程在斯卡拉(17.3節)所採取的提取物

爲了更容易從一成不變切換到可變集合,反之亦然,斯卡拉提供了一些語法糖。即使不可變集和地圖不支持真正的方法,斯卡拉給+=提供了一個有用的替代解釋。當你寫a += b,並a不支持一個名爲+=方法,斯卡拉會嘗試將其解釋爲a = a + b

如果您繼續閱讀在這一節中,你會發現一個更透徹的解釋,用實例。

+3

當在類本身沒有定義時,還應該提及'+ ='的語法糖翻譯。 – Kigyo 2014-10-20 15:40:40

+0

@Kigyo公平點,完成。 – 2014-10-20 15:54:06

+0

啊感謝您確認它是語法糖。我認爲這是發生了什麼,但不確定。我面臨的問題是,我正在閱讀的書中的例子出現在第3章,明確的解釋直到第17章(我還沒有完成)才做出。他們應該已經使用過這方面的內容或者使用了不同的例子。好吧。 – 2014-10-20 18:08:05