2013-02-09 91 views
1

考慮以下幾點:可變或不可變集?

scala> val myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 
<console>:9: error: reassignment to val 
       myset += 3 
        ^

scala> var myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 

scala> myset 
res47: scala.collection.immutable.Set[Int] = Set(1, 2, 3) 

在一種情況下,我可以添加「亞歷克斯」而在另一個我不能。 我知道val和var之間的區別。然而,在這兩種情況下我都困惑了,Scala告訴我這個Set是不可變的,但它允許不同的行爲。

我不想只是因爲在oncase myset是一個val,在一個它是一個變種。我想得到更深入的回答,而不是解釋爲什麼在這兩種情況下Scala都說myset是一個不可變的集合,但兩者的處理方式不同。因爲這是違反直覺的。

例如,使用可變集合並將不可變集合聲明爲var有任何區別嗎? 爲什麼斯卡拉讓你彎曲規則?如果說它是不可變的,它會不會更好呢?

謝謝。

回答

3

首先,讓我們來翻譯+=呼叫

val myset = Set(1,2) 
myset = myset + 3 //this is what the compiler does for myset += 3 

這意味着我們實際上調用+方法上Set,其scaladoc

創建集與額外的元素,除非元素已經存在。因此

什麼代碼試圖做的是創建一個新的Set與添加的元素,並將其重新分配給一成不變參考myset

現在,如果我們改變引用一個可變的一個(使用var),那麼你可以用新做的和不可改變Set(1,2,3)

原設定重新分配它(1,2)仍然是不變的,沒有規則被打破。讓我們從一個案例解釋

var myset = Set(1,2) 
val holdIt = Some(myset) 
myset += 3 
println(myset) // will print Set(1, 2, 3) 
println(holdIt)// will print Some(Set(1, 2)) 

正如你可以看到,原來Set,這是由Option拍攝,從未改變,我們只是重新分配它的變量引用到新創建的Set

2

當你使用一個不可變的Set,將會創建一個新的Set並將其重新分配到var,這在使用val時是不可能的。但是一個可變的Set可以被改變。雖然下面是不是一個完美的保存演示,但它仍然表明,隨着不可變Set一個新的對象被創建,以及可變設置實例保持不變:

scala> var set1 = Set(1, 2) 
set1: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> System.identityHashCode(set1) 
res0: Int = 2119337193 

scala> set1 += 3 

scala> System.identityHashCode(set1) 
res2: Int = 1866831260 

scala> var set2 = collection.mutable.Set(1, 2) 
set2: scala.collection.mutable.Set[Int] = Set(2, 1) 

scala> System.identityHashCode(set2) 
res3: Int = 594308521 

scala> set2 += 3 
res4: scala.collection.mutable.Set[Int] = Set(2, 1, 3) 

scala> System.identityHashCode(set2) 
res5: Int = 594308521 
2

考慮myset作爲指針和Set(1,2)爲對象

val myset的情況下只能指定一次指針&不能指向不同的對象(即指針是不可改變),其中在var myset情況下 可以分配任意時間&可以指向不同的對象(即指針是可變

在兩種情況下對象Set(1,2)是不可變的。

當你

scala> val myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 
<console>:9: error: reassignment to val 
       myset += 3 
        ^

myset += 3實際上給你一個新的Set3追加到它..

由於myset指針是不可變的,你不能重新分配給由+方法返回的新object

,其中在

scala> var myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 

由於myset指針的情況下是可變的,你可以重新分配給由+方法返回的新object