Reputation: 4371
given:
val m = Map[String, Int]("a" -> 1, "b" -> 2, "c" -> 3)
m.foreach((key: String, value: Int) => println(">>> key=" + key + ", value=" + value))
why does the compiler complain
error: type mismatch
found : (String, Int) => Unit
required: (String, Int) => ?
Upvotes: 54
Views: 74250
Reputation: 519
Docs says argument is tuple -> unit, so We can easily do this
Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2)))
Upvotes: 1
Reputation: 4659
Yet another way:
Map(1 -> 1, 2 -> 2).foreach(((x: Int, y: Int) => ???).tupled)
However it requires explicit type annotations, so I prefer partial functions.
Upvotes: 0
Reputation: 10852
The confusing error message is a compiler bug, which should be fixed in 2.9.2:
Upvotes: 14
Reputation: 1137
Excellent question! Even when explicitly typing the foreach method, it still gives that very unclear compile error. There are ways around it, but I can't understand why this example does not work.
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)}
^
Upvotes: 5
Reputation: 4371
oops, read the doco wrong, map.foreach expects a function literal with a tuple argument!
so
m.foreach((e: (String, Int)) => println(e._1 + "=" + e._2))
works
Upvotes: 36
Reputation: 11985
You need to patter-match on the Tuple2
argument to assign variables to its subparts key
, value
. You can do with very few changes:
m.foreach{ case (key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
Upvotes: 19
Reputation: 9742
I'm not sure about the error, but you can achieve what you want as follows:
m.foreach(p => println(">>> key=" + p._1 + ", value=" + p._2))
That is, foreach
takes a function that takes a pair and returns Unit
, not a function that takes two arguments: here, p
has type (String, Int)
.
Another way to write it is:
m.foreach { case (key, value) => println(">>> key=" + key + ", value=" + value) }
In this case, the { case ... }
block is a partial function.
Upvotes: 82