这里对Groovy闭包的进阶操作进行介绍
Composition组合
Groovy支持对多个闭包进行组合。特别地, 闭包还重载了左移<<、右移>>运算符,。使得非常方便实现将一个闭包的输出作为另一个闭包的输入,示例如下所示
1 | class CompositionDemo { |
Currying柯里化
具体到Groovy当中,其闭包的柯里化可以实现对原来接收N个参数的闭包,仅确定其中的部分参数,并使之返回一个新的闭包。在新闭包中仅包含未确定的参数。典型地,Groovy支持左柯里化、右柯里化、指定参数位置的柯里化等多种形式。示例如下所示
1 | class CurryingDemo { |
Memoization记忆化
在递归过程中,如果记住某些重复计算的结果,则可以大大减少计算量。典型地,通过递归的形式计算斐波那契数列的第N项时,其会产生多次重复的计算调用过程。这个时候我们在Groovy闭包中就可以引入Memoization记忆化这一特性,缓存已经计算过的结果
1 | class MemoizationDemo { |
进一步地,还可以通过有参版本的memoize方法实现对缓存结果数量的限制。包括最多、最少以及指定范围数的缓存数。示例代码如下所示
1 | class MemoizationDemo { |
Trampoline蹦床
对于递归而言,其最大风险就在于由于递归过深导致的SOF栈溢出。在Groovy中不论是普通递归还是尾递归,均存在上述风险。示例代码如下所示
1 | class TrampolineDemo { |
通过test2的代码,我们实际上可以发现Groovy并未对尾递归形式作进一步优化,使得其依然存在SOF栈溢出的风险。但在Groovy中则可对尾递归应用trampoline,使得Groovy能够对尾递归的调用进行优化,避免发生SOF。这实际上也是我们使用尾递归写法的真正意义所在。具体地。一方面,在递归闭包时通过trampoline方法传参;另一方面,在定义闭包过程中,则通过无参版本的trampoline方法将闭包包装为TrampolineClosure。示例如下所示
1 | class TrampolineDemo { |
参考文献
- Groovy In Action · 2nd Edition Dierk König、Guillaume Laforge著