Scala學習筆記——(Loan Pattern)借貸模式

Scala中的Loan Pattern

 資源回收是計算機工程實踐中一項重要的實現模式。對於具有GC的程序設計語言,它僅僅實現了內存資源的自動回收,而對於諸如文件IO,數據庫連接,Socket連接等資源需要程序員自行實現資源的回收。
 該問題可以形式化地描述爲:給定一個資源R,並將資源傳遞給用戶空間,並回調算法f: R => T;當過程結束時資源自動釋放。

- Input: Given resource: R
- OutputT
- AlgorithmCall back to user namespace: f: R => T, and make sure resource be closed on done.

因此,該實現模式也常常被稱爲「借貸模式」,是保證資源自動回收的重要機制。本文通過using的抽象控制,透視Scala在這個領域的設計技術,以便鞏固「按名傳遞」技術的應用。

簡單實現

/**
  * 名字調用和值調用
  */
object manage {

  def apply[R <: {def close() : Unit}, T](resource: => R)(f: R => T) = {
    var res: Option[R] = None
    try {
      res = Some(resource)
      f(res.get)
    } catch {
      case NonFatal(ex) => println(s"Non fatal exception! $ex")
    } finally {
      if(res != None) {
        println(s"Closing resource ...")
        res.get.close()
      }
    }
  }
}

等價於

object using {

  type Closeable = { def close(): Unit }

  def apply[T <: Closeable, R](resource: => T)(f: T => R): R = {
    var source = null.asInstanceOf[T]
    try {
      source = resource
      f(source)
    } finally {
      if (source != null) source.close
    }
  }

}

 統計一個文件的行數調用如下:

object TryCatchARM extends App{

  def countLines(fileName:String): Unit = {
    println("count file lines")
    using(Source.fromFile(fileName)) { source =>
      val size = source.getLines.size
      println(s"file $fileName has $size lines")
      if(size > 20) throw new RuntimeException("Big file")
    }
  }

  args foreach(arg => countLines(arg))
}

R <: {def close() : Unit}等價於type Closeable = { def close(): Unit }定義了一個Closeable的類型別名,使得T必須是具有close方法的子類型,這是Scala支持「鴨子編程」的一種重要技術。例如,File滿足T類型的特徵,它具有close方法。
 這樣,不管是什麼對象,只要它擁有一個close():Unit的函數,都可以在這裏使用,並且這個close最後將被自動調用。

惰性求值

 resource: => T是按照by-name傳遞,在實參傳遞形參過程中,並未對實參進行立即求值,而將求值推延至resource: => T的調用點。
 對於本例,using(Source.fromFile(source))語句中,Source.fromFile(source)並沒有馬上發生調用並傳遞給形參,而將求值推延至source = resource語句。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章