Groovy: 为什么闭包不能访问自己?

Groovy: Why can't the closure access itself?

我是 Groovy 新手。当我 运行 以下脚本 Groovy 报告 "No such property: tailFactorial for class ***"。闭包不应该访问局部变量 tailFactorial 吗?

def factorial(int factorialFor) {
    def tailFactorial = { int number, BigInteger theFactorial = 1 ->
        number == 1 ? theFactorial :
        tailFactorial.trampoline(number - 1, number * theFactorial)
    }.trampoline()
    tailFactorial(factorialFor)
}
println "factorial of 5 is ${factorial(5)}"
println "Number of bits in the result is ${factorial(5000).bitCount()}"

让我感到困惑的是,如果我将上面的代码更改为以下代码:

def factorial(int factorialFor) {
    def tailFactorial
    tailFactorial = { int number, BigInteger theFactorial = 1 ->
        number == 1 ? theFactorial :
        tailFactorial.trampoline(number - 1, number * theFactorial)
    }.trampoline()
    tailFactorial(factorialFor)
}
println "factorial of 5 is ${factorial(5)}"
println "Number of bits in the result is ${factorial(5000).bitCount()}"

运行很好。

我们可以发现,这两段代码的唯一区别在于,第一段代码同时声明和定义了闭包,而第二段代码声明了闭包,但没有定义。定义在单独的行中。

怎么会这样?我正在使用 Groovy 2.4.3 和 Java 7,期待您的帮助。谢谢

您无法访问闭包将分配给的变量,因为它会在 右侧(或至少未捕获 get)之后突然出现。

这就是为什么第二个示例(与 groovy 文档中的代码相同)有效的原因。该变量已经声明,闭包可以通过这个名称捕获它。 (请记住,它不是立即执行的闭包代码 - 在这个确切的时间点 tailFactorial 将为空)。

但是由于您只对闭包上的 trampoline 调用感兴趣,所以您可以简单地在闭包本身上调用它。 trampolineClosure:

的一个方法
def factorial(int factorialFor) {
    def tailFactorial = { int number, BigInteger theFactorial = 1 ->
        number == 1 ? theFactorial :
        // XXX
        trampoline(number - 1, number * theFactorial)
    }.trampoline()
    tailFactorial(factorialFor)
}
println "factorial of 5 is ${factorial(5)}"
println "Number of bits in the result is ${factorial(5000).bitCount()}"