2

抱歉,我最近在第 685 页的第 2 版“Scala 编程”中看到了一个示例,这对我来说似乎很奇怪:

var hashSet: Set[C] = new collection.immutable.HashSet
hashSet += elem1

怎么可能添加一些不可变的集合?我尝试了 REPL,它工作正常!

> scala
Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> var s : Set[Int] = collection.immutable.HashSet()
s: Set[Int] = Set()

scala> s += 1324

scala> println(s)
Set(1324)

奇怪的事实是 += 运算符没有在immutable.HashSet api 页面中定义。有人可以帮我理解发生了什么吗?

谢谢。

4

3 回答 3

5

您没有添加到HashSet. 您正在分配给hashSet,这很好,因为hashSet是 a var,而不是 a val

Scala 语言规范 (SLS) 的第 6.12.4 节赋值运算符解释了这些复合赋值运算符是如何脱糖的:

l ω= r

ω除了<,>!不以 开头的任何运算符字符序列在哪里=)被取消糖分到

l.ω=(r)

iff l具有或可隐式转换为具有名为 的成员的对象ω=

否则,它会被脱糖

l = l.ω(r)

(除了l保证只评估一次),如果类型检查。

这允许像+=在其他语言中一样工作,但仍然被覆盖以做不同的事情。

于 2015-04-27T09:56:05.947 回答
3

观察这一点:

scala> var hashSet: Set[Int] = new collection.immutable.HashSet
hashSet: Set[Int] = Set()

scala> val set2 = hashSet + 1234
set2: scala.collection.immutable.Set[Int] = Set(1234)

scala> set2
res20: scala.collection.immutable.Set[Int] = Set(1234)

scala> hashSet
res21: Set[Int] = Set()

所以没有任何东西被添加到不可变的 hashSet 中。hashSet和建造时一样。+完全返回一个新集合,原始集合不变。

当你这样做时hashSet += 1234,它是 Scala 的简写(注意HashSet+=中不存在方法):

val temp = hashSet + 1234
hashSet = temp

+=将适用于遵循协议的任何类。总之当你做a += 12a必须有一个方法返回与's+相同的类型并且应该是可分配的(即 a 。它不适用于 val。试试这个:)。aavarval i = 23; i+=1

于 2015-04-27T05:11:37.373 回答
2

简短的回答

你有一个var,所以你可以重新分配给它。所以+=在这种情况下将被翻译成

hashSet = hashSet + elem

就像其他类型一样,只要+在它们上定义

var i = 0
i += 1
i = i + 1

细节

immutable.HashSeth+方法

使用附加元素创建一个新集合,除非该元素已经存在。

根据文档

+=此类中没有定义方法,因此编译器+=会为您提供一个合成方法,它充当运算符,只需通过传递右操作数并将结果分配回左操作数来调用左操作数上的方法。+

于 2015-04-27T05:15:44.853 回答