了解Scala可变集val参考

时间:2017-08-21 23:57:04

标签: scala

在“Scala编程”第三版中,我看到了一个我无法理解的例子。为了理解它,我将它输入到scala解释器中:

scala> import scala.collection.mutable
import scala.collection.mutable

scala> val movieSet = mutable.Set("Hitch", "Poltergeist")
movieSet: scala.collection.mutable.Set[String] = Set(Poltergeist, Hitch)

scala> movieSet
res3: scala.collection.mutable.Set[String] = Set(Poltergeist, Hitch)  <<< res3

scala> movieSet += "Shrek"
res4: movieSet.type = Set(Poltergeist, Shrek, Hitch)                  <<< res4

我的理解是当在一个mutable上做+ =时。该Set应该就地变异(即它所分配的变量不应该改变),但是引用从res3变为res4。 另外,我理解“val movieSet”来创建一个无法更改的值。这不应该导致“val movieSet”保留res3引用,而不是更改为res4吗?

2 个答案:

答案 0 :(得分:0)

res3res4只是对同一对象的附加引用,每当您键入具有非单位返回类型但未分配给变量的表达式时,由scala shell生成。当你执行+=时,该方法会改变集合,并再次返回对同一对象的引用,这样res3res4最终会包含这些内容。

您可以使用eq方法检查两个值实际上是完全相同的对象(而不是两个相等的对象)。即,res3 eq movieSetres4 eq movieSet都应该是真的。

val限制变量始终引用同一个对象,但它不会限制该对象以任何方式进行变异。

答案 1 :(得分:0)

mutable.Set#+=已签名

trait Set[A] {
  def +=(elem: A): this.type
}

也就是说,它添加了一个元素,然后返回自己,大概是因为你可以链接像set += "a" += "b"这样的调用。 REPL为返回生成新val的事实纯粹是因为它不知道更好。如果你之后输入res3,你会看到变异。