2011-12-22 139 views
44

给出:斯卡拉地图的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) => ? 

回答

25

oops,读取doco错误,map.foreach需要带有元组参数的函数文本!

所以

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

工作

+4

由于涉及的类型是推断的,你可以简单地做:m.foreach(e => println(e._1 +“=”+ e._2) – virtualeyes 2011-12-23 13:57:35

+0

是否可以显示完整的类型?有很多地图,我很关心它是哪一个。 – 2015-09-23 07:24:20

71

我不知道有关错误的,但你可以达到你想要的东西如下:

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

也就是说,foreach采取一对函数并返回Unit,而不是函数t帽子需要两个参数:这里,p的类型为(String, Int)

另一种方式把它写为:

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

在这种情况下,{ case ... }块是一个局部函数。

+0

这很好,更符合动态语言obj.each {K,V => ...}的做法,更比元组可读性更强._1,._2语法 – virtualeyes 2011-12-23 14:00:26

+0

Jut好奇,第二用法(case)有任何性能考虑吗?对于每个元素尝试'大小写'他们分配给变量等。我希望我的代码可读,但也尽可能快。 – endertunc 2015-12-14 10:01:59

13

您需要对参数Tuple2进行模式匹配,以将变量分配给其子部分key,value。你可以做很少的更改:

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

顺便说一下,您可以从键和值中删除类型注释。 – Rogach 2011-12-23 05:14:42

+0

@huitseeker我非常爱你。 – 2015-04-01 17:12:23

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 2013-01-14 21:53:19

+0

我刚刚检查过(通过编译https://github.com/paulbutcher/baderrormessage同时针对2.9.1和2.9。 2)我可以在2.9.1中看到这个问题,而不是在2.9.2中。如果您仍然有问题的例子,那么您应该重新打开该错误? – 2013-01-14 22:35:33

+0

我刚刚使用Scala 2.9.2(Java HotSpot 1.7.0 VM for Windows 64-bit)在@(Eishay Smith)答案中发布的代码(我相信问题中显示的确切问题)并可以看到他帖子中显示的同样荒谬的信息。 – Renato 2013-01-14 22:42:16

0

还有一种方法:

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

但是它需要显式类型注解,所以我更喜欢的部分功能。

1

文档说的说法是元组 - >单元,因此我们可以很容易地做到这一点

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