C#程序员的Scala之路第八章(控制抽象,高阶函数)

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 高级编程

 

你可能感兴趣的:(scala)