2010-06-24 3 views
4

Groovy에서 재귀를 사용하여 트리 관계를 트래버스하려고합니다. 아래 코드는 childNodes & & recurClosure (childNodes)까지 하나의 사이클을 실행하지만 클로저 recurClosure를 다시 호출하지 않습니다. 그 즉시 childNodes에는 루트와 동일한 유형의 두 객체 (배열 목록)가있었습니다.groovy (grails)에서 재귀

코드에서 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) 

는 뿌리 내부 폐쇄 그것의 각 요소를 가져 재귀 익명 폐쇄 호출 ArrayList를이다. 각 클로저 내부에서 '콜'을 움직이면 외부 익명 클로저를 호출하지 않고 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 나의 발견을 업데이트 할 수 있습니다 is owner.call (childNodes)

답변

10

문제는 그

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

당신이 돈에 의해 클로저를 recurClosure에 할당하지 말고 반환 값을 호출하십시오! air_blob이 제안,

먼저 폐쇄를 정의하고 별도로 전화 : 따라서, 물론, 당신은 recurClosure() 통해 폐쇄 ...

두 가지 가능한 솔루션을 호출 할 수 없습니다

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

재귀를 위해 암시 적 call() 함수를 사용하십시오. 이렇게하면 익명 폐쇄로 작업 할 수도 있습니다.아주 좋은 방법은 그루비에서 재귀를 구현하는 IMHO : 코드에

{ 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. 재귀 호출을 닫으 려하지 마십시오 안에 the each? 코드에

또 다른 (상위 레벨) 비고 : 부모와 자녀가 Domain.list() 사실도 모든 어린이를 반환하지 않습니다, 동일한 유형 (Domain)의 경우? 트리를 수동으로 가로 질러 갈 필요가 있습니까?

+0

Daniel .. 코드에서 모든 실수를 잡아 냄으로써 답을 보게되어 기쁩니다. 글쎄, 내 코드 목록을 수정하여 질문을 더 간단하게 만들었습니다. 그래서, 1. returnList를 배열리스트로 정의했습니다. 2. 나는 동의한다. 3. 당신이 옳다. 내가 원했던 것 (나는 효과를보기 위해 그 종결 안팎으로 진술을 움직이려고했다.). 나는 분명히 도메인 클래스에 대한 목록()을 작성하지 않았으며 실제로 다른 테이블에서 가져왔다. 나는 당신 같은 전문가를 오도하려 들지 않았다. (groovy와 grails 모두 : - |). 나는 익명 폐쇄 구현을 시도하고있다. .. 약간의 업데이트가있을 것이다. 많이 감사한다. – bsr

+0

와우, 탁월한 대답 +1 – codeporn

+0

Daniel , 좀 더 자세한 내용으로 질문을 업데이 트했습니다. 이제 질문은 '전화'를 통해 외부 익명 폐쇄를 호출하는 방법입니다. 다시 한 번 감사드립니다. – bsr

2

예외가 있습니까? 은 다음과 같이 별도로 호출 시도 유무 :

def recurClosure 
recurClosure = {inroot -> 
    [... stuff ...] 
} 

recurClosure(root) 

정확하게 당신이이 줄에서 원하는 작업 :

childNodes && recurClosure(childNodes) 
+0

suggetions 주셔서 감사합니다. 예외가 업데이트되었습니다. childNode && recurClosure (childNodes)의 의도는 childnode가 null이 될 때까지 재귀를 계속하는 것이 었습니다. 배열 목록 null 될 수 있습니다, 그래서 (childNodes.size()> 0) & recurClosure (childNodes)하지만 동일한 결과를 시도했다. 예외적으로 클로저에 액세스 할 수없는 것처럼 보입니다. – bsr

관련 문제