Вопрос

I am reading Seven Languages in Seven Weeks to get the taste of different programming paradigm. In the chapter about Scala, I found out that collection are immutable (at least the one from scala.collection.immutable).
However, there is an example which confuses me:

scala> val hashMap = HashMap(0->0)
scala> hashMap += 1->1
scala> hashMap
res42: scala.collection.mutable.HashMap[Int,Int] = Map(1 -> 1, 0 -> 0)

but

scala> map = map + 2->2
<console>:9: error: reassignment to val
       map = map + 2->2

Is it += reassigning an immutable collection? How is that that += can reassign a val HashMap while = fails?
Moreover, I tried out with other collections (List and Map) and with "primitive" (Int) and += fails with the reassignment error. How are HashMaps special? I do not read anything particular in the Scala API and I cannot find a definition for += operator (I am assuming it to be an operator and not a function even in Scala, as well as in C++ or Java).
Sorry for the dumb question, but since I am new to Scala I am having difficulties finding resources by myself.

Это было полезно?

Решение 3

There are two types of collections in Scala: Mutable and Immutable

  1. Mutable: http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.mutable.package
  2. Immutable: http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.immutable.package

What you used definitely belongs to mutable category and hence can be reassigned. In fact, if you try this:

val hashMap = scala.collection.immutable.HashMap(0->0)
hashMap += (1->1)

you'll get same error

Другие советы

You're right that this works with a var, where the compiler can take

hashMap += 1->1

and desugar it to

hashMap = hashMap + 1->1

But there's another possibility too. If your hashMap is of the type scala.collection.mutable.hashMap then it directly calls the += method defined on that type:

hashMap.+=(1->1)

No val is reassigned, the map just internally mutates itself.

hashMap in code sample is collection.mutable.HashMap[Int,Int]. Note the mutable package.

There is a mutable version for many scala collections.

And there is method with name += in mutable.HashMap.

Unlike some other languages, x += y doesn't always compile into x = x + y in Scala. hashMap += 1->1 is actually an infix method call (+= is a valid method name in Scala), which is defined in mutable.HashMap class.

Your first example uses mutable HashMap, as you can see in the last line. Immutable HashMap doesn't have += method.

Note that for a mutable HashMap

scala> val map = scala.collection.mutable.HashMap[Int,Int](0 -> 0)
map: scala.collection.mutable.HashMap[Int,Int] = Map(0 -> 0)

its contents can be changed without using val or var,

scala> map += 1->1
res1: map.type = Map(1 -> 1, 0 -> 0)
scala> map += 2->2
res2: map.type = Map(2 -> 2, 1 -> 1, 0 -> 0)
scala> map
res3: scala.collection.mutable.HashMap[Int,Int] = Map(2 -> 2, 1 -> 1, 0 -> 0)

However for an immutable HashMap declared with val

scala> val imap = scala.collection.immutable.HashMap[Int,Int](0 -> 0)
imap: scala.collection.immutable.HashMap[Int,Int] = Map(0 -> 0)

we cannot for instance add new pairs,

scala> imap += 1->1
<console>:10: error: value += is not a member of scala.collection.immutable.HashMap[Int,Int]
              imap += 1->1
                   ^

However we can create a new HashMap from the original and add a new pair,

scala> val imap2 = imap.updated(1,1)
imap2: scala.collection.immutable.HashMap[Int,Int] = Map(0 -> 0, 1 -> 1)

Even so, an immutable HashMap declared with var

scala> var imap = scala.collection.immutable.HashMap[Int,Int](0 -> 0)
imap: scala.collection.immutable.HashMap[Int,Int] = Map(0 -> 0)

allows for updating the contents,

scala> imap += 1->1
scala> imap
res11: scala.collection.immutable.HashMap[Int,Int] = Map(0 -> 0, 1 -> 1)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top