2011-12-22 32 views
44

dado:Scala Mapa foreach

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

por qué se queja el compilador

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

Respuesta

25

Uy, leer el mana mal, map.foreach espera un literal de la función con un argumento tupla!

por lo

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

obras

+4

Dado que los tipos implicados se deducen, simplemente puede hacer: m.foreach (e => println (e._1 + "=" + e._2) – virtualeyes

+0

¿Es posible mostrar el tipo completo? Hay una gran cantidad de Mapas , Me preocupa cuál es. –

71

no estoy seguro sobre el error, pero se puede lograr lo que desea de la siguiente manera:

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

Es decir, foreach toma una función que toma un par y devuelve Unit, no una función t hat toma dos argumentos: aquí, p tiene tipo (String, Int).

Otra manera de escribir es:

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

En este caso, el bloque { case ... } es una función parcial.

+0

que es bueno, más en línea con obj.each lenguaje dinámico enfoque {k, v => ...} y más legible que la tupla ._1, .2 sintaxis – virtualeyes

+0

Siente curiosidad, ¿hay alguna consideración de rendimiento para el segundo uso (caso)? Para cada elemento trato de 'casarlos' asignándolos a variables, etc. Quiero que mi código sea legible pero también lo más rápido posible. – endertunc

13

Debe establecer coincidencias en el argumento Tuple2 para asignar variables a sus subpartes key, value. Que puede hacer con muy pocos cambios:

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

Y, por cierto, puede eliminar las anotaciones de tipo de la clave y el valor. – Rogach

+0

@huitseeker Te amo mucho. –

5

Excelente pregunta! Incluso al tipear explícitamente el método foreach, todavía da un error de compilación muy poco claro. Hay formas de evitarlo, pero no puedo entender por qué este ejemplo no funciona.

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

El mensaje de error confuso es un error del compilador, que debe ser fixed in 2.9.2:

+0

Uso de Scalac 2.9.2 y este error persiste. – Renato

+0

Acabo de comprobar (compilando https://github.com/paulbutcher/baderrormessage tanto en 2.9.1 como en 2.9. 2). Puedo ver el problema en 2.9.1 y no en 2.9.2.Si tiene un ejemplo del problema que todavía ocurre, ¿quizás debería volver a abrir el error? –

+0

Acabo de probar el código publicado en la respuesta por @ (Eishay Smith) a continuación (creo que es exactamente el mismo problema que se muestra en la pregunta) con Scala 2.9.2 (Java HotSpot 1.7.0 VM para Windows 64-bit) y puede ver el mismo mensaje absurdo que se muestra en su publicación. – Renato

0

embargo, otra forma:

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

Sin embargo se requiere anotaciones de tipo explícitas, por lo que prefieren funciones parciales.

1

Docs dice argumento es tupla -> unidad, por lo que podemos hacer fácilmente este

Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2))) 
Cuestiones relacionadas