关于柯里化(curry)

在实际使用的过程中对柯里化有了一些无法从书本上直接获得的感受。

在JAVA中函数不是头等公民,必须通过接口进行外观统一以后,才能通过实例作为载体进行处理逻辑的传递,

最容易理解的例子莫过于Strategy Pattern,这里就不复述这个概念了。

但是实际上大家都应该遇见过参数个数或者类型无法完全统一的困扰,这个时候我们是怎么办的呢?参数个数不统一,我们可以通过使用构造函数在生成实例的时候传递进去,参数类型不统一的话只能通过Adaptor或者额外抽象出一层来解决,在JAVA中也只能做到这样了。

如何避免这个问题的呢?需要两个前提:1.函数是头等公民可以自由传递;2.柯里化

看起来函数式完全符合要求,这两个前提的组合下可以很轻量的解决我们在JAVA中遇见的问题:

def commonOp[T](list: List[T])(f: List[T] => List[T]): Option[List[T]] = {
    list match {
      case h :: t => Some(f(t))
      case _ => None
    }
  }

  val list = List(1, 3, 4, 5)

  val tailer = (list: List[Int]) => list
  val adder = (n: Int) => (list: List[Int]) => n :: list

  println(commonOp(list)(tailer)) //打印的结果是去掉了头的list,List(3,4,5) 
  println(commonOp(list)(adder(5))) 
  //打印的结果是替换了头的List,List(5,3,4,5),这里应用了柯里化函数的第一个参数,目的就是整形函数外观

 例子可能有些牵强,但这里只是想表达柯里化如何工作而已,不必在意。

tailer传入一个List,不做任何处理直接返回

adder传入一个List和一个n,把n作为头加在list的前面

commonOp两个参数,list和处理list的function,其中function的入参是list,出参也是list

上面的tailer和adder都需要带入到commonOp的第二个function函数参数中。

commonOp的function函数参数实际的类型是Function1,tailer直接带入没有问题,但是adder就不行了,

所以要在外部将adder变成一个偏应用函数,先传入n之后,类型从Function2变成了Function1,柯里化可以对函数外观进行整形,偏应用函数也有同样作用

很轻巧,和JAVA的重量天壤之别。

posted @ 2015-10-30 11:46  thinking!!!  阅读(617)  评论(0编辑  收藏  举报