Карта Scala foreach

дано:

val m = Map[String, Int]("a" -> 1, "b" -> 2, "c" -> 3)
m.foreach((key: String, value: Int) => println(">>> key=" + key + ", value=" + value))

почему компилятор жалуется

error: type mismatch
found   : (String, Int) => Unit
required: (String, Int) => ?

person Dzhu    schedule 22.12.2011    source источник


Ответы (7)


Я не уверен в ошибке, но вы можете добиться того, чего хотите, следующим образом:

m.foreach(p => println(">>> key=" + p._1 + ", value=" + p._2))

То есть foreach принимает функцию, которая принимает пару и возвращает Unit, а не функцию, которая принимает два аргумента: здесь p имеет тип (String, Int).

Другой способ написать это:

m.foreach { case (key, value) => println(">>> key=" + key + ", value=" + value) }

В этом случае блок { case ... } является частичной функцией.

person Philippe    schedule 22.12.2011
comment
это хорошо, больше соответствует подходу динамического языка obj.each {k,v =› ...} и более читабельно, чем синтаксис кортежа ._1, ._2 - person virtualeyes; 23.12.2011
comment
Любопытно, есть ли соображения производительности для второго использования (случая)? Для каждого элемента попробуйте «присвоить» им значение переменной и т. д. Я хочу, чтобы мой код был читабельным, но при этом максимально быстрым. - person endertunc; 14.12.2015

упс, неправильно прочитал документ, map.foreach ожидает функциональный литерал с аргументом кортежа!

so

m.foreach((e: (String, Int)) => println(e._1 + "=" + e._2))

работает

person Dzhu    schedule 22.12.2011
comment
Учитывая, что задействованные типы выводятся, вы можете просто сделать: m.foreach(e => println(e._1 + = + e._2) - person virtualeyes; 23.12.2011
comment
Можно ли показать полный тип? Есть много Карт, я беспокоюсь о том, какая именно. - person Alexey Berezkin; 23.09.2015

Вам необходимо сопоставить аргумент Tuple2, чтобы назначить переменные его подчастям key, value. Вы можете сделать очень мало изменений:

m.foreach{ case (key: String, value: Int) => println(">>> key=" + key + ", value=" + value)} 
person Francois G    schedule 22.12.2011
comment
И, кстати, вы можете удалить аннотации типа из ключа и значения. - person Rogach; 23.12.2011

Запутанное сообщение об ошибке — это ошибка компилятора, которая должна быть исправлена ​​в версии 2.9.2. :

person Paul Butcher    schedule 23.12.2011
comment
Я только что проверил (скомпилировав github.com/paulbutcher/baderrormessage как для 2.9.1, так и для 2.9 .2). Я вижу проблему в 2.9.1, а не в 2.9.2. Если у вас есть пример проблемы, которая все еще возникает, возможно, вам следует снова открыть ошибку? - person Paul Butcher; 15.01.2013
comment
Я только что попробовал код, опубликованный в ответе @(Eishay Smith) ниже (я считаю, что это та же самая проблема, что и в вопросе) со Scala 2.9.2 (Java HotSpot 1.7.0 VM для 64-разрядной версии Windows) и можно увидеть такое же абсурдное сообщение, показанное в его посте. - person Renato; 15.01.2013
comment
Вот что происходит, когда я компилирую ваш код из Git: Добро пожаловать в Scala версии 2.9.2 (Java HotSpot™ 64-Bit Server VM, Java 1.7.0). Введите выражения для их оценки. Введите :help для получения дополнительной информации. scala› класс Foo расширяет Function2[Int, Int, Int] { | def применить (x: Int, y: Int) = x + y | переопределить определение кортежа: (Int, Int) =› Int = super.tuple | } ‹console›:9: ошибка: несоответствие типов; found : ((Int, Int)) => Int required: (Int, Int) => Int override def tupled: (Int, Int) => Int = super.tuple ^ - person Renato; 15.01.2013
comment
Это сообщение об ошибке верно. Обратите внимание, что в найденной строке есть два набора скобок. Ошибка заключалась в том, что он печатал только один набор скобок. Если вы попробуете это в 2.9.1 и сравните вывод, вы увидите, что они разные. - person Paul Butcher; 15.01.2013

Отличный вопрос! Даже при явном вводе метода foreach он все равно выдает очень непонятную ошибку компиляции. Есть способы обойти это, но я не могу понять, почему этот пример не работает.

scala> m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
<console>:16: error: type mismatch;
 found   : (String, Int) => Unit
 required: (String, Int) => Unit
              m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
                                                         ^
person Eishay Smith    schedule 22.12.2011

Документы говорят, что аргументом является кортеж -> единица, поэтому мы можем легко сделать это

Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2)))
person vikashait    schedule 05.07.2015

Еще один способ:

Map(1 -> 1, 2 -> 2).foreach(((x: Int, y: Int) => ???).tupled)

Однако для этого требуются явные аннотации типов, поэтому я предпочитаю частичные функции.

person Yaroslav    schedule 27.09.2013