scala匿名函数问题

时间:2011-08-22 22:08:36

标签: function scala lambda

我正在尝试在scala中将字符串从字符串过滤到int,我遇到了一个奇怪的问题。

如果我将以下内容放入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)

我的问题是错误消息和额外的一对括号是怎么回事?如果我尝试添加一组额外的括号,我会收到错误:不是合法的形式参数。

2 个答案:

答案 0 :(得分:16)

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

让它发挥作用的两种方法:

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

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

第一个通过模式匹配工作,第二个通过将函数(String, Int) => Boolean转换为((String, Int)) => Boolean

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

答案 1 :(得分:6)

filter接受只接受一个参数的函数。在表达式中,表达式接受两个参数。但是,元素碰巧是一对,所以你可能认为你可以给出两个参数。放置它的正确方法是:

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

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