38

2 つの不変マップを連結すると、右側のオペランドの要素が左側の要素を「上書き」するようです。

scala> List((1, 2), (5, 6)).toMap ++ List((5, 9)).toMap
res13: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 5 -> 9)

scala> List((5, 9)).toMap ++ List((1, 2), (5, 6)).toMap
res14: scala.collection.immutable.Map[Int,Int] = Map(5 -> 6, 1 -> 2)

これが Scala のルールであるかどうかを知りたいですか?

Scala API からは、この質問を理解できませんでした。

4

2 に答える 2

26

はい、この動作は一定です

于 2012-07-31T14:31:23.083 に答える
14

Map.++ は次のように定義されます。

override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] =
    ((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _)

wherereprは現在のマップであり、xs.seq渡したマップに格納されているペア/マッピングのシーケンスを提供します++


Map./: は次のように記述されます。

def /:[B](z: B)(op: (B, (A, B)) ⇒ B): B

Applies a binary operator to a start value and all elements of this
immutable map, going left to right.

Note: /: is alternate syntax for foldLeft;
z /: xs is the same as xs foldLeft z.

順序付けられていないマップで「左から右」が何を意味するかは指定されていないことに注意してください。


++以下は、デバッグprintlnステートメントを 再実装して拡張することにより、舞台裏で何が起こっているかを示しています。

val m1 = Map(1 -> "A", 2 -> "B", 3 -> "C")
val m2 = Map(2 -> "X", 3 -> "Y", 4 -> "Z")

println(m1.repr)
  /* Map(1 -> A, 2 -> B, 3 -> C) */
println(m1.repr.getClass.getName)
  /* scala.collection.immutable.Map$Map3 */

def ++[K, V](ts: Map[K, V], xs: Map[K, V]): Map[K, V] =
  (ts /: xs)  {case (acc, entry) =>
                println("acc = " + acc)
                println("entry = " + entry)
                acc + entry
              }

val m3 = ++(m1, m2)
  /*
    acc = Map(1 -> A, 2 -> B, 3 -> C)
    entry = (2,X)
    acc = Map(1 -> A, 2 -> X, 3 -> C)
    entry = (3,Y)
    acc = Map(1 -> A, 2 -> X, 3 -> Y)
    entry = (4,Z)
  */

println(m3)
  /* Map(1 -> A, 2 -> X, 3 -> Y, 4 -> Z) */
于 2012-07-31T16:23:41.270 に答える