2011-08-22 86 views
4

我想过滤一个地图从字符串到斯卡拉整数,我遇到了一个奇怪的问题。斯卡拉匿名功能的问题

如果我把下列REPL:

scala> val myMap = Map("a" -> 1, "b" -> 2, "c" -> 3) 
myMap: scala.collection.immutable.Map[java.lang.String,Int] = 
| Map(a -> 1, b -> 2, c -> 3) 

它的确定,到目前为止,这个工程......

scala> myMap.filter(_._2 > 1) 
res9: scala.collection.immutable.Map[java.lang.String,Int] = Map(b -> 2, c -> 3) 

但失败...

scala> myMap.filter((k:java.lang.String, v:Int) => v > 1) 
<console>:9: error: type mismatch; 
found : (java.lang.String, Int) => Boolean 
required: ((java.lang.String, Int)) => Boolean 
    myMap.filter((k:java.lang.String, v:Int) => v > 1) 

我的问题是错误信息和多余的括号是怎么回事?如果我尝试添加一组额外的括号,则会出现错误:不是合法的形式参数。

回答

16

myMap.filter预计Tuple2[String, Int] => Boolean类型的函数,相当于((String, Int)) => Boolean。你传递给它一个类型为(String, Int) => Boolean的函数;也就是说,一个函数需要两个参数而不是一个Tuple2

两种方式得到它的工作:通过(String, Int) => Boolean转换功能((String, Int)) => Boolean

myMap.filter { case (k, v) => v > 1 } 

myMap.filter(Function.tupled((k, v) => v > 1)) 

通过模式匹配的首部作品,和第二。

顺便说一下,有关于统一元组和函数参数列表的讨论。也许在未来的Scala版本中,所有函数都将采用一个参数(可能是一个元组)。

+1

对于'Function.tupled'为+1。 – agilesteel

+0

同意。 Function.tupled是显式的,而模式匹配看起来更像是一个技巧。 – andyczerwonka

+1

对不起,如果这是一个愚蠢的问题,但为什么与大小写匹配的模式使用花括号{}但不使用括号? –

6

filter接受只接受一个参数的函数。在您的表达式中,表达式接受两个参数。然而,元素碰巧是一对,所以你可能会认为你可以给出两个参数。把它的正确的方法是这样的:

myMap.filter (p => p._2 > 1) 

也就是说,我收到一对,p,它的第二个元素必须大于1。