web-dev-qa-db-fra.com

Scala Map foreach

donné:

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

pourquoi le compilateur se plaint

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

oups, lisez mal le doco, map.foreach attend un littéral de fonction avec un argument Tuple!

alors

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

travaux

29
Dzhu

Je ne suis pas sûr de l'erreur, mais vous pouvez obtenir ce que vous souhaitez comme suit:

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

Autrement dit, foreach prend une fonction qui prend une paire et renvoie Unit, pas une fonction qui prend deux arguments: ici, p a le type (String, Int).

Une autre façon de l'écrire est:

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

Dans ce cas, le { case ... } block est une fonction partielle.

75
Philippe

Vous devez faire correspondre les motifs sur l'argument Tuple2 Pour affecter des variables à ses sous-parties key, value. Vous pouvez le faire avec très peu de changements:

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

Le message d'erreur déroutant est un bogue du compilateur, qui devrait être corrigé dans 2.9.2 :

14
Paul Butcher

Excellente question! Même en tapant explicitement la méthode foreach, cela donne toujours cette erreur de compilation très peu claire. Il existe des moyens de contourner cela, mais je ne comprends pas pourquoi cet exemple ne fonctionne pas.

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)}
                                                         ^
5
Eishay Smith

Docs dit que l'argument est Tuple -> unité, donc nous pouvons facilement le faire

Map(1 -> 1, 2 -> 2).foreach(Tuple => println(Tuple._1 +" " + Tuple._2)))
1
vikashait

Encore une autre façon:

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

Cependant, cela nécessite des annotations de type explicites, donc je préfère les fonctions partielles.

0
Yaroslav