Reputation: 131
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.
Upvotes: 2
Views: 2216
Reputation: 4300
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
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.
Upvotes: 2
Reputation: 369458
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.
Upvotes: 5
Reputation: 31724
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 (i.e. a var
. It does not work for val. Try this: val i = 23; i+=1
).
Upvotes: 3