`
JohnnyJian
  • 浏览: 104313 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Groovy学习笔记——闭包的递归调用

阅读更多
如果一个闭包被赋值给一个对象的属性(在脚本中,给一个没有定义过的变量赋值,实际上就是给这个脚本对象添加了一个属性),那么当需要对这个闭包进行递归调用的时候,可以直接使用这个属性的名字进行调用:
// 递归求n!
factorialProperty = { n ->
    if (n == 0) return 1
    n * factorialProperty(n - 1) // 使用这个属性的名字进行递归调用
}
assert 3628800 == factorialProperty(10)

如果把闭包赋值给一个局部变量,那么就必须先定义这个变量,再进行赋值:
def factorialVar // 先定义
factorialVar = { n -> // 再赋值
    if (n == 0) return 1
    n * factorialVar(n - 1) // 使用这个局部变量的名字进行递归调用
}
assert 3628800 == factorialVar(10)

但是,如果要在定义局部变量的同时,用闭包初始化这个变量,那么就没有办法使用上面的方法了。这是因为这个闭包先于这个局部变量被定义,所以在这个闭包被定义的时候,在它的上下文中并没有这个局部变量。
在这种情况下,可以通过Closure的call方法实现递归调用:
def factorialVar = { n ->
    if (n == 0) return 1
    n * call(n - 1) // 使用call方法实现递归调用
//    n * factorialVar(n - 1) // 错误
}
assert 3628800 == factorialVar(10)

call方法同样可以用于匿名闭包:
assert 3628800 == { n -> n == 0 ? 1 : n * call(n - 1) }(10)

事实上,call方法可以用在任何闭包的递归调用上。

以上代码在Groovy 1.5.7中测试通过。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics