理解Scala:将函数作为参数传递

C0d*_*ack 6 scala

我开始学习Scala,我遇到了Scala编程教科书的片段,我不太明白.希望有人可以帮助我吗?

这是来自Scala编程的清单9.1,第2版.

object FileMatcher {
    private def filesHere = (new java.io.File(".")).listFiles
}

private def filesMatching(matcher: String => Boolean) = 
    for (file <- filesHere; if matcher(file.getName)) yield file

def filesEnding(query: String) = 
    filesMatching(_.endsWith(query)) // ???

def filesContaining(query: String) = 
    filesMatching(_.contains(query)) // ???

def filesRegex(query: String) = 
    filesMatching(_.matches(query)) // ???
Run Code Online (Sandbox Code Playgroud)

我对这些线条有点困惑// ???.使用_不知何故创建一个传递给匿名的函数filesMatching?或者_与此无关,而编译器认为filesMatching需要一个函数,因此不_.endsWith(query)作为表达式执行,而是使表达式成为函数?

pag*_*_5b 14

扩展定义

匿名函数以其更详细和完整的形式定义为

(a: A, b: B, ...) => function body //using a, b, ...
Run Code Online (Sandbox Code Playgroud)

例如

(a: String, b: String) => a ++ b // concatenates 2 Strings
Run Code Online (Sandbox Code Playgroud)

推断类型

如果上下文提供了所需的信息(如高阶函数需要其函数参数的特定签名),则可以省略参数的类型,如

(a, b, ...) => function body //using a, b, ...
Run Code Online (Sandbox Code Playgroud)

例如

val l = List(1, 2, 3)

//you can omit the type because filter on List[Int] expects a (Int => Boolean)
l.filter(i => i < 3)
Run Code Online (Sandbox Code Playgroud)

占位符语法

最后,如果您的参数每次使用一次,并且按照您声明它们的顺序使用,则可以使用更短的形式,如函数体所示,

_ ++ _ // which is equivalent to (a, b) => a ++ b
Run Code Online (Sandbox Code Playgroud)

每个_都是函数参数的占位符

例如

filesMatching的参数是类型的函数,String => Boolean所以你可以使用

_.endsWith(query) // equivalent to (s: String) => s.endsWith(query)
_.contains(query) // equivalent to (s: String) => s.contains(query)
_.matches(query)  // equivalent to (s: String) => s.matches(query)
Run Code Online (Sandbox Code Playgroud)