在 “彻底”函数式编程 一文中,咱们初步感觉了函数式编程的力量:以很是简洁的代码,经过组合任何短小的简单函数,实现更加复杂功能的复合函数。html
有小伙伴可能会问: 既然函数是这么重要的原材料,那么从哪里能够获取这么多原材料呢 ?总不成,一个个去定义吧。别急,Curry 提供了批量生产函数的能力,—— 若是星云是恒星的工厂,那么,Curry 就是函数的工厂。编程
本文将以 Groovy 为示例,讲解 Curry 的特性及能力。
框架
小伙伴都学过多元函数,好比 f(x,y) = x^2 + y ,当 y = 0 时,就变成 f(x) = x^2 平方函数; 当 x = 1 时,就变成 f(y) = 1+y 线性函数。 Curry ,通俗地说,就是将多变量的函数,经过逐个因变量赋值,从而批量生成函数的能力。函数式编程
以下代码所示: def closure = { x,y -> x^2 +y } 定义了一个二元函数 f(x,y) , rcurry(0) 便是将 y 赋值为 0 (右边的参数),这样就获得了一元函数 square(x) = x^2 ; curry(1) 便是将 x 赋值为 1 (默认是左边的参数),就获得了 linear(y) = 1+y 。 嗯,就是这么简单。函数
class Basics { static void main(args) { def closure = { x,y -> x * x +y } def square = closure.rcurry(0) println((1..5).collect { square(it) }) def linear = closure.curry(1) println((1..5).collect { linear(it) }) } }
输出结果:this
[1, 4, 9, 16, 25] [2, 3, 4, 5, 6]
那么 Curry 有什么实际应用呢 ? 总不能只停留在数学的领域里。 实际上 Curry 的能力很是强大。咱们来实现一个通用调用器。在实际工程中,经常须要调用具备相同参数的函数,或者对不一样的对象进行相同的处理。code
假设有两个订单处理函数: cancel, complete ,有一个列表排序函数 sort:htm
def static sort(list) { list.sort() return list } def static cancel(order) { println ("cancel: " + order.orderNo) } def static complete(order) { println ("complete: " + order.orderNo) } class OrderParam { def orderNo def shopId }
能够定义一个二元函数 generalCaller ,能够对指定的参数对象 param 使用指定的 handler 进行处理。对象
def generalCaller = { param, handler -> handler(param) }
如今,来看怎么使用:blog
第一种方式:指定参数对象。 能够构造一个订单对象,使用 Curry ,就获得了能够处理这个订单的函数处理器 orderProcessor, 而后就能够传入不一样的订单处理器进行处理。this.&method 是 Groovy 对函数的引用。
def orderProcessor = generalCaller.curry(new OrderParam(orderNo: 'E0001', shopId: 55)) orderProcessor(this.&cancel) orderProcessor(this.&complete)
第二种方式,指定处理器。 就获得了一个对参数进行排序的函数 sort(param) , 而后传入不一样的可排序对象进行处理:
def sorter = generalCaller.rcurry(this.&sort) println sorter([4,7,2,6,1,3]) println sorter(["i", "have", "a", "dream"])
是否是很是灵活 ? 在 “函数柯里化(Currying)示例” 一文中,使用 Curry 实现了一个简易的文件处理框架。
Curry 能够将高维函数逐步降维,批量生成大量的低维函数。 若是有一个 N 维函数,思考下,经过 Curry ,能够生成多少个低维函数 ?Curry 结合函数式编程,蕴藏着惊人的潜力。