可变映射内支持不可变映射的不可变操作

3
我今天写代码时注意到了一个奇怪的行为。似乎不可变映射嵌套在可变映射中允许使用(通常是可变的)+=运算符。
scala> val myMutableMap = mutable.Map[String, scala.collection.immutable.Map[String, String]]()
myMutableMap: scala.collection.mutable.Map[String,scala.collection.immutable.Map[String,String]] = Map()

scala> myMutableMap += "outerkey" -> scala.collection.immutable.Map("k1"-> "v1")
res25: myMutableMap.type = Map(outerkey -> Map(k1 -> v1))

scala> myMutableMap("outerkey") += "k2"->"v2"

scala> myMutableMap
res27: scala.collection.mutable.Map[String,scala.collection.immutable.Map[String,String]] = Map(outerkey -> Map(k1 -> v1, k2 -> v2))

scala> val huhwhat = myMutableMap("outerkey")
huhwhat: scala.collection.immutable.Map[String,String] = Map(k1 -> v1, k2 -> v2)

scala> huhwhat += "k3"->"k4"
<console>:21: error: value += is not a member of scala.collection.immutable.Map[String,String]
              huhwhat += "k3"->"k4"

我查看了Map.scala源代码,但没有发现+=操作符可以从哪里继承。

这是在Scala 2.11.5上。有人知道发生了什么吗?

1个回答

3
myMutableMap("outerkey") += "k2"->"v2"

被编译器解释为

myMutableMap("outerkey") = myMutableMap("outerkey") + ("k2"->"v2")

即,从不可变的myMutableMap("outerkey")创建一个新的映射,并添加键("k2"->"v2"),并使用新对("outerkey" -> <the new map>)更新myMutableMap。 这是通过mutable.MapLikeupdate方法实现的,该方法提供了foo(x) = y的行为。有关更多信息,请参见此博客文章(还有一个SO答案列出了Scala中的一堆其他魔术函数)。

1
更准确地说:如果Scala找不到合适的+=(或-= ...)方法,它将再次尝试使用foo = foo + bar并使用它,如果它可以通过类型检查。 反过来,foo(bar) = baz被解释为foo.update(bar, baz),它基本上相当于apply的“setter”等效项。 - Jörg W Mittag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接