Ожидается ли эта удивительная (для меня) разница в поведении Map в Scala 2.8.0 и 2.7.7? - PullRequest
2 голосов
/ 22 октября 2010

Похоже - в Scala 2.8.0 - если вы отобразите () экземпляр 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, которое опиралось на старое поведение.

Обновление:

Как указал ниже Крис Наттикомб, чтение Миграция из Scala 2.7 могло бы быть хорошим началом, прежде чем задавать этот вопрос :) В частности, упоминается использование флага компилятора -Xmigration, который кажется чрезвычайно полезным при портировании.

1 Ответ

7 голосов
/ 22 октября 2010

Да, это предполагаемое поведение; В самом деле, включение такого рода вещей было главным пунктом редизайна системы коллекций в 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))

Насколько это задокументировано, это широко обсуждается здесь: http://www.scala -lang.org / node / 2060 и (еще более) здесь: http://www.scala -lang орг / доку / файлы / сборники-апи / collections.html

...