集合(Set)はイミュータブル版とミュータブル版があるんだよ
名前空間が違うので完全名は違うけど以下の2つがある
ちなみに普通に初期化してしまうと、問答無用でイミュータブル版になるので注意。
イミュータブル版は要素の追加に注意が必要
その前にまずミュータブル版の追加方法を見る。
scala> import scala.collection.mutable.Set import scala.collection.mutable.Set scala> val mutableSet = Set("Mutable", "Set") mutableSet: scala.collection.mutable.Set[java.lang.String] = Set(Set, Mutable) scala> mutableSet += "AddValue" scala> println(mutableSet) Set(Set, Mutable, AddValue)
ミュータブルオブジェクトなので初期化時にvalでOK。
続いてイミュータブル版、まず同じように書いてみる。
scala> import scala.collection.immutable.Set import scala.collection.immutable.Set scala> val immutableSet = Set("Immutable", "Set") immutableSet: scala.collection.immutable.Set[java.lang.String] = Set(Immutable, Set) scala> immutableSet += "AddValue" <console>:7: error: reassignment to val immutableSet += "AddValue" ^
という感じに失敗してしまいます。
「+=」の扱いの違い
同じように「+=」を使いましたが、コンパイラはその動作を変えます。
まず、ミュータブルなSetに関してはそのまま「+=」というメソッドを持ちます。つまり、
scala> mutableSet.+=("AddValue2")
という書き方ができます。
対してイミュータブルなSetは「+=」というメソッドを持ちません。ではどうなっているのか、以下のように展開されています。
immutableSet = immutableSet + "AddValue"
そうです。再代入されているだけなのです。ここで引っかかるのは初期化時のvalですね。再代入不可のvalを使ったので失敗してしまったのですよ。
つまり、以下のようにすれば大丈夫です。
scala> var immutableSet2 = Set("Immutable", "Set") immutableSet2: scala.collection.immutable.Set[java.lang.String] = Set(Immutable, Set) ^ scala> immutableSet2 += "AddValue" scala> println(immutableSet2) Set(Immutable, Set, AddValue)
> Scala スケーラブルプログラミング - 第03章