首页 > 代码库 > 控制抽象

控制抽象

Control Abstraction  控制抽象 个人理解就是控制结构??

scala里并没有太多的控制结构。但scala可以让你定义自己的控制抽象

1.用函数值定义控制抽象2.柯里化3.传名参数

 1.用函数值定义控制抽象

object FileMatcher {

  private def filesHere = (new java.io.File(".")).listFiles()

  /**
    *
    * @param query 查询字段 such as .scala结尾的文件
    * @return
    */
  def filesEnding(query:String) = {
    for (file <- filesHere; if file.getName.endsWith(query))
      yield file
  }

  def filesContaining(query:String) = {
    for (file <- filesHere; if file.getName.contains(query))
      yield file
  }

  def filesRegex(query:String) = {
    for (file <- filesHere; if file.getName.matches(query))
      yield file
  }

}

 重复代码太多了。

object FileMatcher {

  private def filesHere = (new java.io.File(".")).listFiles()


  private def helperFileMatching(query:String,matcher:(String,String) => Boolean) = {
    for (file <- filesHere; if (matcher(file.getName,query)))
      yield file
  }
  
  def filesEnding(query:String) = helperFileMatching(query,_.endsWith(_))

  def filesContaining(query:String) = helperFileMatching(query, _.contains(_))

  def filesRegex(query:String) = helperFileMatching(query, _.matches(_))

}

 通过函数值减少代码。

object FileMatcher {

  private def filesHere = (new java.io.File(".")).listFiles()


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

  def filesEnding(query:String) = helperFileMatching(_.endsWith(query))

  def filesContaining(query:String) = helperFileMatching(_.contains(query))

  def filesRegex(query:String) = helperFileMatching(_.matches(query))

}

 通过闭包进一步减少代码。

 

java简化代码的方式》》???

 

上面的例子通过高阶函数简化代码。下面介绍将高阶函数放置在API中,可以调用者简化代码。

 

写两个方法。一个是判断一个列表里是否有负数(参数为列表),一个是判断列表里的数是否为奇数

scala通过将高阶函数写入api中简化客户端代码

scala> def containsNeg(xs:List[Int]) = xs.exists(_ < 0)
containsNeg: (xs: List[Int])Boolean

 

scala> def containsNeg(xs:List[Int]) = xs.exists(_ % 2 ==0)
containsNeg: (xs: List[Int])Boolean

 

2.柯里化

让控制抽象更像原生控制结构

柯里化的函数参数应该至少两个。通过分割函数参数实现柯里化

scala> def sum(a:Int,b:Int,c:Int) = a+b+c
sum: (a: Int, b: Int, c: Int)Int

scala> def sum(a:Int)(b:Int)(c:Int) = a+b+c
sum: (a: Int)(b: Int)(c: Int)Int

 

双倍控制结构

scala> def twice(op:Double => Double, x:Double) = op(op(x))
twice: (op: Double => Double, x: Double)Double

 

IO流的借贷模式

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)
)

  通过高阶函数。为客户端代码封装了打开关闭文件操作。

当且仅当函数参数只有一个时候可以将函数调用的中括号改成花括号   

这里在定义withPrintWriter的时候柯里化参数,可以使得withPrintWriter的调用更像控制抽象(原生控制结构)

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


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

上面的withPrintWriter书中说应为{}带有参数writer =>所以不太像if语句,可以通过传名参数改善???

 

3.传名参数(很重要)

在参数前增加 => ,函数只有在函数体用到参数时才计算参数,而不是在函数用之前。

 

控制抽象