当声明为var时,Scala不可变集是可变的

时间:2014-10-20 15:28:28

标签: scala set immutability mutable

我正在阅读Scala编程,第2版(精彩的书,比斯卡拉的网站更好地以非摇滚科学的方式解释事物)并且我注意到了这一点...过时的奇怪不可变和可变集。

它将以下内容声明为不可变集

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

然后声明只有Mutable集定义了+ =方法。好吧,这很有道理。问题是这段代码有效。在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

但是,如果我将Set声明为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 Immutable 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)

我的猜测是,由于一些隐藏的语法糖,Scala认识到它是一个Var并允许你用新构造的集合替换它。

1 个答案:

答案 0 :(得分:14)

可变的不是Set,是对它的引用。

a += "Colleen"

返回一个新的不可变集,分配给可变变量a

Scala执行语法转换,将表达式转换为

a = a + "Colleen"

如果未定义+=(如不可变Set的话)

+=a时,显然val没有意义,因为你无法重新分配它,因此被禁止。

这里摘录自 Scala编程(第17.3节)

  

为了更容易从不可变集合切换到可变集合,反之亦然,Scala提供了一些语法糖。尽管不可变集和映射不支持真正的+=方法,但Scala为+=提供了有用的替代解释。每当您撰写a += b,而a不支持名为+=的方法时,Scala会尝试将其解释为a = a + b

如果您继续阅读该部分,您将通过示例找到更全面的解释。