對于支持函數(shù)作為“頭等公民”的語言,你可以有效的創(chuàng)建新的控制結構即使該語言語法上固定的。你所要做的事創(chuàng)建一個方法,該方法使用函數(shù)類型作為參數(shù)。
比如: 下面為一個“雙倍”的控制結構,這個“雙倍”控制結構可以重復一個操作,然后返回結果。
scala> def twice (op:Double => Double, x:Double) =op(op(x))
twice: (op: Double => Double, x: Double)Double
scala> twice(_ + 1, 5)
res0: Double = 7.0
上面調用 twice ,其中 _+1 調用兩次,也就是 5 調用兩次 +1,結果為 7。
你在寫代碼時,如果發(fā)現(xiàn)某些操作需要重復多次,你就可以試著將這個重復操作寫成新的控制結構,在前面我們定義過一個 filesMatching 函數(shù)
def filesMatching(
matcher: (String) => Boolean) = {
for(file <- filesHere; if matcher(file.getName))
yield file
}
如果我們把這個函數(shù)進一步通用化,可以定義一個通用操作如下:
打開一個資源,然后對資源進行處理,最后釋放資源,你可以為這個“模式”定義一個通用的控制結構如下:
def withPrintWriter (file: File, op: PrintWriter => Unit) {
val writer=new PrintWriter(file)
try{
op(writer)
}finally{
writer.close()
}
}
使用上面定義,我們使用如下調用:
withPrintWriter(
new File("date.txt"),
writer => writer.println(new java.util.Date)
)
使用這個方法的優(yōu)點在于 withPrintWriter,而不是用戶定義的代碼,withPrintWriter 可以保證文件在使用完成后被關閉,也就是不可能發(fā)生忘記關閉文件的事件。這種技術成為“租賃模式”,這是因為這種類型的控制結構,比如 withPrintWriter 將一個 PrintWriter 對象“租”給 op 操作,當這個 op 操作完成后,它通知不再需要租用的資源,在 finally 中可以保證資源被釋放,而無論 op 是否出現(xiàn)異常。
這里調用語法還是使用函數(shù)通常的調用方法,使用()來列出參數(shù),在 Scala 中如果你調用函數(shù)只有一個參數(shù),你可以使用{}來替代().比如下面兩種語法是等價的:
scala> println ("Hello,World")
Hello,World
scala> println { "Hello,world" }
Hello,world
上面第二種用法,使用{}替代了(),但這只適用在使用一個參數(shù)的調用情況。 前面定義 withPrintWriter 函數(shù)使用了兩個參數(shù),因此不能使用{}來替代(),但如果我們使用柯里化重新定義下這個函數(shù)如下:
import scala.io._
import java.io._
def withPrintWriter (file: File)( op: PrintWriter => Unit) {
val writer=new PrintWriter(file)
try{
op(writer)
}finally{
writer.close()
}
}
將一個參數(shù)列表,變成兩個參數(shù)列表,每個列表含一個參數(shù),這樣我們就可以使用如下語法來調用
withPrintWriter
val file = new File("date.txt")
withPrintWriter(file){
writer => writer.println(new java.util.Date)
}
第一個參數(shù)我們還是使用()(我們也可以使用{}),第二個參數(shù)我們使用{}來替代(),這樣修改過的代碼使得 withPrintWriter 看起來和 Scala 內置的控制結構語法一樣。