为什么其中一个分裂&过滤工作但不是另一个?

时间:2015-04-09 22:13:41

标签: scala filter

val c = s.split(" ").filter(_.startsWith("#")).filter(x =>  
  x.contains("worcester") || x.contains("energy"))

作品

但这不是

val c = s.split(" ").filter(_.startsWith("#")).filter(_.contains("worcester") || 
  _.contains("energy"))

我还没清楚为什么后者不起作用 - 可能是我的基础知识存在缺陷

非常感谢任何帮助 谢谢 萨米特

1 个答案:

答案 0 :(得分:5)

使用这样的下划线称为占位符语法。因此,_.contains("x")之类的内容相当于x => x.contains("x")。使用占位符语法时,您只能使用每个参数一次。使用多个占位符表示匿名函数的多个参数(然后按下划线的顺序使用)。所以,当你写:

o.filter(_.contains("worcester") || _.contains("energy"))

理论上它等同于

o.filter((x, y) => x.contains("worcester") || y.contains("energy"))

哪个不进行类型检查,因为filter需要Array[String] => Boolean类型的参数。

使用reduce变体时,多个占位符很常见。例如,阶乘可以计算为(1 to n).reduce(_ * _)。这是有效的,因为reduce需要(Int, Int) => Int类型的参数,因此_ * _相当于(x, y) => x * y符合预期类型。

注意占位符语法适用于尽可能小的范围,这一点非常重要。因此,例如,f(g(_))相当于f(x => g(x)),而不是x => f(g(x)),这是一个常见错误。

您可以在Scala here中找到有关使用下划线的完整列表,以及有关占位符语法here的更多信息。