1.高阶函数
这章里我们做一个文件搜索的类如下代码:
object FileMatcher { private def filesHere = (new java.io.File(".")).listFiles() def filesMatching(query: String) = for (file <- filesHere; if file.getName.endsWith(query)) yield file } object LongLines extends App { FileMatcher.filesMatching(".project").foreach(println) }
该类返回一个结尾为.project的文件数组,并且将其打印出来。
现在来了一个新的需求,需要你过滤文件名称中包含一个字符串的文件,对下面代码做了如下修改:
object FileMatcher { private def filesHere = (new java.io.File(".")).listFiles() def filesMatching(query: String) = for (file <- filesHere; if file.getName.contains(query)) yield file } object LongLines extends App { FileMatcher.filesMatching("project").foreach(println) }
这段代码与上面一段很像,那么我们有什么办法重用起来呢?
如果写一个contains方法,与endsWith方法作为参数传递,是不是就解决问题了?
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 filesContains(query: String) = filesMatching(query, _.contains(_)) def filesEndsWith(query: String) = filesMatching(query, _.endsWith(_)) } object LongLines extends App { FileMatcher.filesContains("p").foreach(println) FileMatcher.filesEndsWith(".project").foreach(println) }
这代码有点绕,首先在filesMathching里添加了一个matcher:(String,String) => Boolean 的一个函数参数,
然年添加了2个函数,filesContains与filesEndsWith2个函数,关键就是在 _.contains(_)里了
我们把_.contains(_)作为参数传递给了matcher参数,这里的占位符使用了2次,与matcher(file.getName,query)相对应
第一个占位符是给file.getName占位的,第二个则是给query占位的。
这种函数被称为高阶函数,带其它函数作为参数的函数。
2.编写新的控制
打开资源对它操作,然后关闭资源你可以使用如下的方法将其捕获并放入控制抽象:
import java.io.File import java.io.PrintWriter object LongLines extends App { def withPrintWrite(file: File, op: PrintWriter => Unit) { val writer = new PrintWriter(file) try { op(writer) } finally { writer.close() } } withPrintWrite(new File("date.txt"), writer => writer.println(new java.util.Date)) }
这个代码的好处withPrintWriter函数不管业务,确认文件在结尾被关闭,因此忘记关闭文件是不可能的,这个技巧叫贷出模式。
因为控制抽象函数,如withPrintWrite 打开了资源并贷给op使用,op使用完成之后,在由withPrintWrite 函数回收资料。
更多内容请查看scala 高级编程