2011-12-22 3 views
44

Дано:Scala Карта Еогеасп

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

ответ

25

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

так

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

работы

+4

Учитывая, что вовлеченные типы выведены, вы можете просто сделать: m.foreach (e => println (e._1 + "=" + e._2) – virtualeyes

+0

Можно ли показать полный тип? , Я обеспокоен тем, что это такое. –

71

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

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

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

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

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

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

+0

, что приятно, в соответствии с динамическим языком obj.each {к, v => ...} подходом и многими другими читаемый, чем кортеж ._1, ._2 синтаксис – virtualeyes

+0

Juts любопытно, есть ли оценка эффективности для второго использования (case)? Для каждого элемента попробуйте «case» их назначить переменной и т. Д. Я хочу, чтобы мой код читался, а также был максимально быстрым. – endertunc

13

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

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

И вы можете удалить аннотации типа от ключа и значения, между прочим. – Rogach

+0

@huitseeker Я люблю тебя очень дорого. –

5

Отличный вопрос! Даже при явном вводе метода 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)} 
                 ^
14

Сообщение запутанным ошибка компилятора ошибка, которая должна быть fixed in 2.9.2:

+0

Использование scalac 2.9.2, и эта ошибка остается. – Renato

+0

Я только что проверил (компилируя https://github.com/paulbutcher/baderrormessage против обоих 2.9.1 и 2.9. 2). Я вижу проблему в 2.9.1, а не в 2.9.2.Если у вас есть пример проблемы, все еще возникающей, возможно, вам следует снова открыть ошибку? –

+0

Я только что попробовал код, отправленный в ответ by @ (Eishay Smith) ниже (я считаю, та же проблема, что и в вопросе) с Scala 2.9.2 (Java HotSpot 1.7.0 VM для Windows 64-bit) и может видеть то же абсурдное сообщение, показанное в его посте. – Renato

0

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

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

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

1

Docs говорит аргумент кортеж -> блок, так что мы можем легко сделать это

Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2))) 
Смежные вопросы