简体   繁体   中英

Adding to immutable HashSet

Sorry guys, I recently saw an example in "Programming in Scala", 2nd Edition on page 685, which seemed strange to me:

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

How is it possible to add something an immutable collection? I tried on REPL and it worked ok!

> 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)

The stranger fact is that += operator is not defined in immutable.HashSet api page. Could anybody please help me understand what's going on?

Thanks.

You are not adding to the HashSet . You are assigning to hashSet , which is perfectly fine, since hashSet is a var , not a val .

Section 6.12.4 Assignment Operators of the Scala Language Specification (SLS) explains how such compound assignment operators are desugared:

l ω= r

(where ω is any sequence of operator characters other than < , > , ! and doesn't start with = ) gets desugared to

l.ω=(r)

iff l has or is implicitly convertible to an object that has a member named ω= .

Otherwise, it gets desugared to

l = l.ω(r)

(except l is guaranteed to be only evaluated once), if that typechecks.

This allows something like += to work like it does in other languages but still be overridden to do something different.

Observe this:

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()

So nothing gets added to the immutable hashSet. hashSet is the same as it was when constructed. + returns a new set altogether and the original set is unchanged.

When you do hashSet += 1234 , it is a scala shorthand for (note no method += exists in HashSet ):

val temp = hashSet + 1234
hashSet = temp

+= will work for any class which follows this protocol. In short when you do a += 12 . a must have a method + which returns the same type as a 's and a should be assignable (ie a var . It does not work for val. Try this: val i = 23; i+=1 ).

Short answer

You have a var so you can reassign to it. So += in this case will be translated to

hashSet = hashSet + elem

just like other types, as long as + is defined on them

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

Details

immutable.HashSeth has + method which

Creates a new set with an additional element, unless the element is already present.

according to docs .

There is no += method defined in this class, so += will be a synthetic method given to you by compiler which acts as an operator simply calling the + method on the left operand by passing the right operand and assigning the result back to the left operand.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM