grails - groovy 中的递归(grails)

标签 grails groovy

我正在尝试使用groovy中的递归来遍历树关系。下面的代码运行一个周期,直到 childNodes && recurClosure(childNodes ) ,但不会再次调用闭包 recurClosure 。此时 childNodes 有两个与 root 类型相同的对象(数组列表)。

在代码中,定义了 recurClosure 并使用对象列表(根)进行调用。然后它会迭代每个元素并细化子节点(为此使用 grails dsl)。如果 childNodes 不为 null,则会递归调用父方法。

我应该把它分开吗,还是出了什么问题?

def parentval 
def root = Domain.list()

def recurClosure
recurClosure = {inroot ->
  inroot.each {
    returnList << it
    parentval = it
    childNodes = Domain.withCriteria {
      eq('parent', parentval )
    }
  }
  childNodes && recurClosure(childNodes )
}(root)

return returnList

}

提前致谢。

更新:注意到以下异常

    ERROR [2010-06-24 08:20:04,742] [groovy.grails.web.errors.GrailsExceptionResolver] Cannot invoke method call() on null object
java.lang.NullPointerException: Cannot invoke method call() on null object
    at com.bsr.test.DomainService$_closure2_closure7.doCall(com.bsr.test.DomainService:68)
    at com.bsr.test.DomainService$_closure2.doCall(com.bsr.test.DomainService:58)
    at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy:45)
    at com.bsr.test.DomainController$_closure3.doCall(DomainController.groovy)
    at org.apache.shiro.web.servlet.ShiroFilter.executeChain(ShiroFilter.java:687)
    at org.apache.shiro.web.servlet.ShiroFilter.doFilterInternal(ShiroFilter.java:616)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
    at java.lang.Thread.run(Thread.java:619)

更新2:现在尝试丹尼尔的建议。

{ inroot ->
    inroot.each {
        returnList << it
        parentval = it
        childNodes = Domain.withCriteria {
            eq('parent', parentval )
        }
           if(childNodes)
           call(childNodes)
    }
       /*if(childNodes)
        call(childNodes)*/

}(root)

在上面的实现中,root是一个数组列表,内部闭包取出其中的每个元素并递归调用匿名闭包。当我将“调用”移至each 闭包内时,它不会调用外部匿名闭包,而是调用inroot.each {} 本身。所以,我收到一个错误

ERROR [2010-06-24 08:47:46,438] [groovy.grails.web.errors.GrailsExceptionResolver] instance not of expected entity type: java.util.ArrayList is not a: com.bsr.test.Domain

我看到一篇关于如何通过 'this' 命名闭包的博文> 我会更新我的发现..谢谢

更新3:调用外层闭包的方法是owner.call(childNodes)

最佳答案

问题是,通过

recurClosure = {
    [...]
}(root)

您没有将闭包分配给 recurClosure ,而是其调用的返回值!因此,当然,您不能通过 recurClosure() 调用闭包。 ...

两种可能的解决方案:

首先定义闭包,然后单独调用它,如air_blob建议的:

def recurClosure = {
    [...]
}
recurClosure(root)

使用隐式call()递归函数。这样你甚至可以使用匿名闭包。恕我直言,这是在 Groovy 中实现递归的一个非常好的方法:

{ inroot ->
    inroot.each {
        returnList << it
        parentval = it
        childNodes = Domain.withCriteria {
            eq('parent', parentval )
        }
    }
    if(childNodes)
        call(childNodes)
}(root)

对您的代码还有两条评论:

  1. 您可能需要申报 returnList :def returnList = []
  2. 同时childNodes && recurClosure(childNodes )可以做你想做的事,牺牲一个字符并拼出 if 更具可读性.. ;-)
  3. 您不想在 each 内递归调用您的闭包吗? ?

关于您的代码的另一个(更高级别)注释:如果 parent 和他们的 child 属于同一类型( Domain ),则不会 Domain.list()实际上也归还所有 child 吗?真的需要手动遍历树吗?

关于grails - groovy 中的递归(grails),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3107112/

相关文章:

grails - 根据用户角色隐藏内容?

grails - 保存实例时使用Grails映射解决异常

java - Groovyc 和 Java 12 预览功能

date - Groovy 无法将字符串解析为日期

jenkins - 如何访问参数化构建中的参数?

grails - Cereal ,哥伦。按 parent 找 child ,按 child 找 parent

tomcat - 在 Tomcat7 上部署 Grails Portlet 时出错

grails - Grails从smb下载文件

java - 为什么 Groovy Enums 无法访问类变量?

grails - 在 Groovy 中覆盖 Joda DateTime toString