我不明白为什么作者说"Scala编程"的代码清单9.1使用了闭包.在第9章中,他们展示了如何将代码重构为更复杂的形式,从这个原始代码:
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
def filesEnding(query: String) =
for (file <- filesHere; if file.getName.endsWith(query))
yield file
def filesContaining(query: String) =
for (file <- filesHere; if file.getName.contains(query))
yield file
def filesRegex(query: String) =
for (file <- filesHere; if file.getName.matches(query))
yield file
}
Run Code Online (Sandbox Code Playgroud)
到第二个版本:
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
def filesMatching(query: String,
matcher: (String, String) => Boolean) = {
for (file <- filesHere; if matcher(file.getName, query))
yield file
}
def filesEnding(query: String) =
filesMatching(query, _.endsWith(_))
def filesContaining(query: String) =
filesMatching(query, _.contains(_))
def filesRegex(query: String) =
filesMatching(query, _.matches(_))
}
Run Code Online (Sandbox Code Playgroud)
他们说这里没有关闭.现在我明白了.但是他们引入了使用闭包来重构甚至更多,如代码清单9.1所示:
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)
现在他们说查询是一个自由变量,但我真的不明白他们为什么这么说?由于""查询""似乎从顶部方法明确地传递到字符串匹配函数.
Eug*_*ota 17
让我们看看What is a closure中的经典add-n闭包.
(define (add a)
(lambda (b)
(+ a b)))
(define add3 (add 3))
(add3 4) returns 7
Run Code Online (Sandbox Code Playgroud)
在上面的lambda表达式中,a
是自由变量,它在Wikipedia链接中定义为:
函数中引用的变量,不是局部变量或该函数的参数.upvalue是一个自由变量,它已被一个闭包绑定(关闭).
回来
def filesEnding(query: String) =
filesMatching(_.endsWith(query))
Run Code Online (Sandbox Code Playgroud)
隐函数x => x.endsWith(query)
是头等函数,其被分配给第一级的值matcher
,并_.endsWith()
关闭上query
,类似于3关闭起来的方式a
在(add 3)
.(add3 4)
相当于完成matcher(file.getName)
.
编辑:Tricky部分是Scala中的功能,称为占位符语法匿名函数.通过使用_
代替发送者或参数,Scala自动创建一个匿名函数,我们可以将其视为lambda表达式.
例如,
_ + 1 creates x => x + 1
_ * _ creates (x1, x2) => x1 * x2
_.endsWith(query) creates x => x.endsWith(query)
Run Code Online (Sandbox Code Playgroud)
在函数内x => x.endsWith(query)
,query
满足作为自由变量的两个要求:
query
不是函数中定义的局部变量(没有局部变量).query
不是函数的参数(唯一的参数是x
).