2014-02-07 3 views
2

Я читаю Seven Languages in Seven Weeks, чтобы получить представление о различных парадигмах программирования. В главе о Scala я обнаружил, что коллекция является неизменной (по крайней мере, от scala.collection.immutable).
Однако есть пример, который меня смущает:Scala HashMap: не + = переназначить левую сторону?

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

но

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

ли += переназначения неизменяемой коллекции? Как это может быть += может переназначить valHashMap, в то время как = не удается?
Кроме того, я опробовал другие коллекции (List и Map) и с «примитивным» (Int) и += с ошибкой переназначения. Как HashMap s специальный? Я не читаю ничего особенного в Scala API, и я не могу найти определение для оператора += (я предполагаю, что это оператор, а не функция даже в Scala, а также на C++ или Java).
Извините за немой вопрос, но так как я новичок в Scala, у меня возникают трудности с поиском ресурсов самостоятельно.

ответ

2

Есть два типа коллекций в Scala: изменяемые и неизменяемые

  1. Mutable: http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.mutable.package
  2. Неизменный: http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.immutable.package

Что вы использовали определенно относится к изменяемым категории и, следовательно, могут быть переназначены , В самом деле, если вы попытаетесь это сделать:

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

вы получите ту же ошибку

+1

Принимаются за ссылки. Я знал, что мне не хватало легкой точки зрения, но я следую за книгой шаг за шагом, и это предложение: «скопируйте и вставьте, прежде чем пытаться закодировать сами», и я пропустил тот факт, что я импортировал «изменчивый HashMap» (на самом деле ссылка, на которую я смотрел, для «неизменной версии»). – ThanksForAllTheFish

3

hashMap в образце кода collection.mutable.HashMap[Int,Int]. Обратите внимание на пакет mutable.

Существует версия mutable для многих коллекций scala.

И есть метод с именем += в mutable.HashMap.

4

Вы правы, что это работает с var, где компилятор может принять

hashMap += 1->1 

и desugar до

hashMap = hashMap + 1->1 

Но есть и другая возможность. Если hashMap имеет тип scala.collection.mutable.hashMap, то он напрямую вызывает метод +=, определенный на этом типе:

hashMap.+=(1->1) 

Нет val переназначен, карта просто внутренне мутирует сам по себе.

2

В отличие от некоторых других языков, x += y не всегда компилируется в x = x + y в Scala. hashMap += 1->1 - фактически вызов метода infix (+= - допустимое имя метода в Scala), которое определено в классе mutable.HashMap.

В первом примере используется изменчивый HashMap, как вы можете видеть в последней строке. Immutable HashMap не имеет += способ.

+0

Спасибо. Я действительно искал функцию '+ =' (это то, что я уже получил, что то, что в Java является оператором в Scala, может быть либо оператором И методом), но, конечно, я не мог найти '+ =' в «неизменяемом API HashMap» – ThanksForAllTheFish

1

Обратите внимание, что в течение изменяемого HashMap

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

его содержания может быть изменена без использования val или 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) 

Однако для неизменного HashMap объявленного с val

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

мы не можем, например, добавлять новые пары,

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

Однако мы можем создать новый HashMap от оригинала и добавить новую пару,

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

Тем не менее, непреложным HashMap объявлен с var

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

позволяет производить обновление содержимого,

scala> imap += 1->1 
scala> imap 
res11: scala.collection.immutable.HashMap[Int,Int] = Map(0 -> 0, 1 -> 1) 
Смежные вопросы