为什么我需要显式执行Groovy trampoline.call()方法进行递归?

时间:2015-09-22 13:08:21

标签: recursion groovy

我正在使用Groovy'递归地运行'进入Map并尝试使用Tail-recursion将所有BigDecimal类型的值更改为Double以避免StackOverFlow。

我已经使用注释@TailRecursive创建了一个方法。现在我尝试使用简单的闭合和蹦床,如下所示:

def mapToTest = [
    key1: "String1",
    key2: new BigDecimal(2),
    key3: "String3",
    key4: [attr1:'attrValue1', attr2: new BigDecimal(4)],
    key5:new BigDecimal(5)
]

def deepDoubler 
deepDoubler = { Map map, boolean rec ->
   println "is rec? ${rec}" 
   map.each { k, v ->
       println (v instanceof Map)
       if (v instanceof Map){
           println "calling recursively... ${v}"
           deepDoubler.trampoline(v, true)
       } else if (v instanceof BigDecimal) {
           map[k] = new Double(0)
       }
    }
}.trampoline()
deepDoubler(mapToTest, false)

我添加了布尔参数只是为了打印,实际上我能够打印“递归调用”#39;但是除非我在trampoline指令之后添加方法call(),否则永远不会执行该方法。

if (v instanceof Map){
 println "calling recursively... ${v}"
 deepDoubler.trampoline(v, true).call() // call() here otherwise it doesn't run

有没有人知道为什么它在我执行call()方法时有效?我尝试了很多API示例,并且在没有显式调用()的情况下运行良好,但我没有找到Map的任何示例。

谢谢!

1 个答案:

答案 0 :(得分:0)

trampoline方法不调用闭包但装饰它并返回修改后的闭包 - 请参阅here。您需要通过()call()明确调用装饰闭包。