这对于Scala 2.8.0和2.7.7中预期的Map行为有何不同(对我而言)?

时间:2010-10-22 17:17:56

标签: scala map scala-2.8

看起来 - 在Scala 2.8.0中 - 如果你将Map实例映射到一个2元组的序列,你最终会得到一个Map。当发生这种情况时,任何具有相同第一个元素的2元组都被视为重复元素,并且您最终只能得到最后一个元素。这与2.7.7中发生的情况不同。通过示例更容易理解。

Scala 2.7.7:

scala> val m = Map("a" -> 1, "b" -> 2, "c" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1, b -> 2, c -> 3)

scala> m.map { case (k, v) => ("foo", v) }
res5: Iterable[(java.lang.String, Int)] = ArrayBuffer((foo,1), (foo,2), (foo,3))

Scala 2.8.0:

scala> val m = Map("a" -> 1, "b" -> 2, "c" -> 3)
m: scala.collection.immutable.Map[java.lang.String,Int] = Map((a,1), (b,2), (c,3))

scala> m.map { case (k, v) => ("foo", v) }
res16: scala.collection.immutable.Map[java.lang.String,Int] = Map((foo,3))

这是预期的吗?变更是否记录在某处?这似乎是一个合理的想法,但是我花了很多时间来升级依赖于旧行为的2.7.7应用程序。

更新:

正如Kris Nuttycombe在下面指出的那样,在提出这个问题之前阅读Migrating from Scala 2.7可能是一个好的开始:)特别是它提到使用编译器标志-Xmigration,这在移植时似乎非常有用。

1 个答案:

答案 0 :(得分:7)

是的,这是预期的行为;实际上,启用此类功能是2.8中重新设计系列系统的重点。默认情况下,Scala将在应用map函数时选择最具体的类型;但是,如果你需要迭代(例如,因为你担心通过重复键消除值,最简单的事情可能是简单地在地图上调用toSeq:

scala> val iter = m.toSeq.map { case (k, v) => ("foo", v) }                                  
iter: Seq[(java.lang.String, Int)] = List((foo,1), (foo,2), (foo,3))

就记录而言,这里有广泛的讨论:http://www.scala-lang.org/node/2060和(更多)这里:http://www.scala-lang.org/docu/files/collections-api/collections.html