Groovy:Why can';难道封闭通道本身不存在吗?

Groovy:Why can';难道封闭通道本身不存在吗?,groovy,Groovy,我是个很棒的新手。当我运行以下脚本时,Groovy报告“没有这样的属性:类***的tailFactorial”。闭包不应该访问局部变量tailFactorial吗 def factorial(int factorialFor) { def tailFactorial = { int number, BigInteger theFactorial = 1 -> number == 1 ? theFactorial : tailFactorial.tra

我是个很棒的新手。当我运行以下脚本时,Groovy报告“没有这样的属性:类***的tailFactorial”。闭包不应该访问局部变量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
将为空)

但是,因为你只对结束时的蹦床调用感兴趣,你可以简单地在结束时调用它
蹦床
是一种
闭合的方法

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()}"

因为在您的第一个代码段中,
tailFactorial
闭包在执行时还不存在,所以它不能从自身内部访问。Val是正确的,在代码的第4行中,您在tailFactorial闭包变量的初始化器中引用了tailFactorial。由于初始值设定项是在声明完成之前执行的,因此tailFactorial变量尚不存在,无法引用。在第二个示例中,首先创建变量,不进行初始化,因此可以在赋值闭包中引用它。@BillJames,我认为闭包声明是可以的,因为初始化执行时闭包的代码不会执行。就像我说的,这是个骗局。我只是不知道这个技巧是如何工作的。您的解决方案确实有效,但我仍然想知道第二个代码段为什么有效。谢谢。@SamuelGong我对俘虏一方做了更好的解释,我认为你是对的。顺便说一下,Groovy闭包的工作原理与JavaScript不同。例如,下面的代码工作得很好:var factorial=function(n){if(n==1){return 1;}else{return n*factorial(n-1);}}}alert(factorial(5));我的最终理解是,在声明闭包之前,局部变量应该存在,以便闭包可以捕获它们,然后使用它们。我说得对吗,@cfrick?乍一看,我在文件中找不到一个明确的声明,上面写着这样的话。但据我所知,groovy clojures捕获了“高于”自身的变量,而不是自身分配中的LH。是的,你说得对。