Scala 函数式编程_柯里化_Currying

Scala 函数式编程_柯里化_Currying


柯里化

    在计算机科学中,柯里化(英语:Currying) 是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由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============================


你可能感兴趣的:(Scala 函数式编程_柯里化_Currying)