Scala関数式プログラミング_コリー化Currying

3350 ワード

Scala関数式プログラミング_コリー化Currying
コリー化
コンピュータ科学において、コリー化(英語:Currying)は、複数のパラメータを受け入れる関数を1つの単一パラメータ(最初の関数の最初のパラメータ)を受け入れる関数に変換し、残りのパラメータを受け入れて結果を返す新しい関数を返す技術である.この技術はChristopher Stracheyが論理学者のハスケル・ガリーと命名したが、Moses Schonfinkelとゴトロブ・フレグが発明した.
例を直接見る
簡単な関数のコリー化は、次のようになります.
def foo(a: Int): (Int)=>Int = {
  println("===1===")
  def fooF(b: Int): Int = {
    println("===3===")
    a * a + b * b
  }
  println("===2===")
  fooF
}

println((foo(3))(4))

実行結果は、
E:\test-scala>scala currying.scala
===1===
===2===
===3===
25

この例は、関数fooFを返し、この関数を再び呼び出す(より一般的には、返された関数を4に適用する)例であり、次に、匿名関数を返します.
//          (y: Int) => x * y
def mulOneAtATime(x: Int) = (y: Int) => x * y

println(mulOneAtATime(3)(2))

これにより関数のコリー化も実現し,mulOneAtATimeは高次関数でもある.この関数はscalaで以下のように簡単に書くことができます.
def mulOneAtATime2(x: Int)(y: Int) = x * y

println(mulOneAtATime(3)(2))

lambda式とあまり差がなく,変数x,yをバインドした.
さらに複雑な例を見ると、例えば、ローカルテキストファイルのすべての行データを取得する機能を設計し、メイン関数機能は主にファイルストリーム読取ファイルのすべての行を作成し、読取中にローカルファイルが存在するか否かを判断し、ファイルストリームを読み取り、閉じるなどの多くの補助操作を行う必要がある.
function_app_main.scala
import java.io.{BufferedReader, FileReader, Closeable, File}

def getLinesSelf(filename: String): List[String] = {
  getLines(filename)(isReadable)(closeStream)
}

def getLines(filename: String)(isFileReadable: (File) => Boolean)(closableStream: (Closeable) => Unit): List[String] = {
  val file = new File(filename)
  if (isFileReadable(file)) {
    val readerStream = new FileReader(file)
    val buffer = new BufferedReader(readerStream)
    try {
      var list: List[String] = List()
      var str = ""
      var isReadOver = false
      while (!isReadOver) {
        str = buffer.readLine()
        if (str == null) isReadOver = true
        else list = str :: list
      }
      list.reverse
    } finally {
      closableStream(buffer)
      closableStream(readerStream)
    }
  } else {
    List()
  }
}

def isReadable(file: File) = {
  if (null != file && file.exists() && file.canRead()) true
  else false
}

def closeStream(stream: Closeable) {
  if (null != stream) {
    try {
      stream.close
    } catch {
      case ex: Throwable => println(ex.getMessage)
    }
  }
}

val fileName = "d:/test.txt"
val list: List[String] = getLinesSelf(fileName)
println(list.size)
list.foreach(item => println(item))

このscalaスクリプトを実行すると、
C:\WorkSpace6-scala\scala-train\src\com\usoft>scala function_app_main.scala
あなたが望む結果が見えます.主にこの関数を見てみましょう
getLines(filename: String)(isFileReadable: (File) => Boolean)(closableStream: (Closeable) => Unit): List[String]

この関数は
filename:StringはStringタイプのパラメータfilenameを受信する
(isFileReadable:(File)=>Boolean)パラメータがFileタイプで、Booleanタイプの関数を返します.
(closableStream:(Closeable)=>Unit)Closeableタイプのパラメータを受信し、Unitタイプの関数を返します.
これもコリー化関数のチェーン呼び出しです
getLines(filename)(isReadable)(closeStream)

参照先:http://nerd-is.in/2013-09/scala-learning-higher-order-functions/
http://hongjiang.info/currying-and-builder-pattern/
http://blog.csdn.net/yangguo_2011/article/details/30730185
============================END============================