请考虑以下事项:
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)
在一个案例中我可以添加“alex”而在另一个案例中我不能。 我知道val和var之间的区别。然而,在两种情况下让我困惑的是Scala告诉我Set是不可变的但它允许不同的行为。
我不想那样,因为在oncase myset是一个val而在一个中它是一个var。我想要一个更深层次的答案来解释为什么在两种情况下Scala都说myset是一个不可改变的集合,但却以不同的方式对待它们。因为它是反直觉的。
例如,使用可变集并将不可变集声明为var有什么不同吗? 为什么scala让你屈服于规则?如果说它是不可改变的,那会不会更好呢?
感谢。
答案 0 :(得分:3)
首先让我们翻译+=
电话
val myset = Set(1,2)
myset = myset + 3 //this is what the compiler does for myset += 3
这意味着我们实际上在+
上调用Set
方法,其scaladoc表示
使用其他元素创建 new 集,除非该元素已存在。
因此,代码尝试执行的操作是使用添加的元素创建 new Set
并将其重新分配给不可变引用 {{1} }。
现在,如果我们将引用更改为可变引用(使用myset
),那么您可以将其重新分配给新制作且不可变的 var
原始Set(1,2)仍然是不可变的,没有规则被破坏。让我们用一个案例来解释这个
Set(1,2,3)
正如您所看到的,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
答案 1 :(得分:2)
当您使用不可变集时,将创建一个新集并将其重新分配给var
,这在使用val
时是不可能的。但是一个可变的Set可以变异。虽然以下不是一个完美的保存演示,但它仍然显示使用不可变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 :(得分:2)
将myset
视为指针,将Set(1,2)
视为对象
如果val myset
指针只分配一次&amp;不能指向不同的对象(即指针是不可变的)
在var myset
的情况下可以分配任意时间&amp;可以指向不同的对象(即指针是可变的)
在这两种情况下,对象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
实际上会为您添加一个新的Set
并附加3
..
由于myset
指针是不可变的,因此您无法重新分配object
方法返回的新+
。
其中
的情况scala> var myset = Set(1,2)
myset: scala.collection.immutable.Set[Int] = Set(1, 2)
scala> myset += 3
由于myset
指针是可变的,您可以重新分配object
方法返回的新+
。