Scala 2.8.0 和 2.7.7 中 Map 行为的这种令人惊讶的差异(对我来说)是预期的吗?

发布于 2024-09-29 03:37:56 字数 1124 浏览 0 评论 0原文

在 Scala 2.8.0 中,如果您将一个 Map 实例映射()到一个二元组序列,那么您最终会得到一个 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 在下面指出的,阅读 在提出这个问题之前,从 Scala 2.7 迁移 可能是一个好的开始:) 特别是它提到了使用编译器标志 -Xmigration,这在移植时似乎非常有用。

It looks like -- in Scala 2.8.0 -- if you map() a Map instance to a sequence of 2-tuples that you end up getting a Map back. When this happens, any of the 2-tuples with the same first element are considered duplicates, and you only end up getting the last one. This is different from what happened in 2.7.7. This is easier to understand with an example.

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))

Is this expected? Is the change documented somewhere? It seems like a reasonable idea, but it has cost me a lot of time upgrading a 2.7.7 app that was relying on the old behaviour.

Update:

As pointed out below by Kris Nuttycombe, reading Migrating from Scala 2.7 might have been a good start before asking this question :) In particular it mentions using the compiler flag -Xmigration, which seems extremely useful when porting.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毅然前行 2024-10-06 03:37:56

是的,这是预期的行为;事实上,启用此类功能是 2.8 中收集系统重新设计的一个重点。默认情况下,Scala 在应用映射函数时会选择最具体的类型;但是,如果您需要可迭代(例如,因为您担心通过重复键消除值,最简单的事情可能是简单地在地图上调用 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))

就记录而言,这里进行了广泛讨论:< a href="http://www.scala-lang.org/node/2060" rel="nofollow">http://www.scala-lang.org/node/2060 并且(更是如此)这里: http://www.scala-lang.org/ docu/files/collections-api/collections.html

Yes, this is the intended behavior; indeed, enabling this sort of thing was a major point of the collections system redesign in 2.8. By default, Scala will choose the most specific type that it can when applying the map function; however, if you need the iterable (for example, because you're concerned about elimination of values by duplicate keys the easiest thing is probably to simply call toSeq on the map:

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

As far as this being documented, it is discussed extensively here: http://www.scala-lang.org/node/2060 and (even more so) here: http://www.scala-lang.org/docu/files/collections-api/collections.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文