Scala 創(chuàng)建新的控制結(jié)構(gòu)

2018-09-28 18:25 更新

創(chuàng)建新的控制結(jié)構(gòu)

對于支持函數(shù)作為“頭等公民”的語言,你可以有效的創(chuàng)建新的控制結(jié)構(gòu)即使該語言語法上固定的。你所要做的事創(chuàng)建一個方法,該方法使用函數(shù)類型作為參數(shù)。

比如: 下面為一個“雙倍”的控制結(jié)構(gòu),這個“雙倍”控制結(jié)構(gòu)可以重復(fù)一個操作,然后返回結(jié)果。

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

上面調(diào)用 twice ,其中 _+1 調(diào)用兩次,也就是 5 調(diào)用兩次 +1,結(jié)果為 7。

你在寫代碼時,如果發(fā)現(xiàn)某些操作需要重復(fù)多次,你就可以試著將這個重復(fù)操作寫成新的控制結(jié)構(gòu),在前面我們定義過一個 filesMatching 函數(shù)

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

如果我們把這個函數(shù)進一步通用化,可以定義一個通用操作如下:

打開一個資源,然后對資源進行處理,最后釋放資源,你可以為這個“模式”定義一個通用的控制結(jié)構(gòu)如下:

def withPrintWriter (file: File, op: PrintWriter => Unit) {
  val writer=new PrintWriter(file)
  try{
    op(writer)
  }finally{
    writer.close()
  }
}

使用上面定義,我們使用如下調(diào)用:

withPrintWriter(
   new File("date.txt"),
   writer => writer.println(new java.util.Date)
)

使用這個方法的優(yōu)點在于 withPrintWriter,而不是用戶定義的代碼,withPrintWriter 可以保證文件在使用完成后被關(guān)閉,也就是不可能發(fā)生忘記關(guān)閉文件的事件。這種技術(shù)成為“租賃模式”,這是因為這種類型的控制結(jié)構(gòu),比如 withPrintWriter 將一個 PrintWriter 對象“租”給 op 操作,當(dāng)這個 op 操作完成后,它通知不再需要租用的資源,在 finally 中可以保證資源被釋放,而無論 op 是否出現(xiàn)異常。

這里調(diào)用語法還是使用函數(shù)通常的調(diào)用方法,使用()來列出參數(shù),在 Scala 中如果你調(diào)用函數(shù)只有一個參數(shù),你可以使用{}來替代().比如下面兩種語法是等價的:

scala> println ("Hello,World")
Hello,World
scala> println { "Hello,world" }
Hello,world

上面第二種用法,使用{}替代了(),但這只適用在使用一個參數(shù)的調(diào)用情況。 前面定義 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ù),這樣我們就可以使用如下語法來調(diào)用

withPrintWriter 
val file = new File("date.txt")
withPrintWriter(file){
  writer => writer.println(new java.util.Date)
}

第一個參數(shù)我們還是使用()(我們也可以使用{}),第二個參數(shù)我們使用{}來替代(),這樣修改過的代碼使得 withPrintWriter 看起來和 Scala 內(nèi)置的控制結(jié)構(gòu)語法一樣。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號