2012-02-22 102 views
3

在Grails應用程序中,我試圖阻止在有向圖中創建循環。用戶能夠爲節點分配一個父節點,但是沒有節點應該是它自己的父節點的祖先。我寫了一個簡單的設置函數調用checkLineageForTarget,這是遞歸函數,做繁重:爲什麼這個Groovy閉包不會返回我期望的值?

boolean checkLineageForTarget(Integer target, Collection<Node>stillToProcess){ 
// true means that this is a safe addition 
// false means that this addition creates a cycle 

    boolean retVal = stillToProcess.each { 
     Collection<Node> itsParents = getParentNodes(it) 

     if (it.id == target){ 
      println("found a loop on " + target); 
      return false; // loop detected! 
     } 
     if (itsParents.empty){ return true; } // end of the line 

     return checkLineageForTarget(target, itsParents) 
    } 

    // at this point, retVal is always true, even when the "found a loop [...]" condition is met 
    return retVal; 
} 

這個「作品」,因爲它打印「發現了一個循環[...]」消息,但在閉包之外,retVal爲true,調用函數試圖添加新的父/子關係,並且我的堆棧運行。

我的誤解是什麼?

+0

您可以用'.each'像那樣?我會使用'.every' – zoran119 2012-02-22 01:06:33

+1

它是Grails,而不是「Groovy on Grails」 – 2012-02-22 01:35:41

+0

@Burt哎呀,我的壞。 – 2012-02-22 16:02:51

回答

3

each方法返回它被調用的同一個集合,所以retVal可能不是布爾值「true」,但被評估爲「真實」(因爲它是一個集合,這意味着它不是空的)。

如果要檢查集合中每個元素的條件,可以使用every

boolean checkLineageForTarget(Integer target, Collection<Node>stillToProcess){ 
    stillToProcess.every { node -> 
     node.id != target && checkLineageForTarget(target, getParentNodes(node)) 
    } 
} 

請注意,我並不需要檢查的父節點集合.empty條件,因爲這將被遞歸調用進行過濾,checkLineageForTarget(即在一個空的收集調用.every總是返回true)。同時,由於&&運營商的短路,迭代只要node.id == target :)

+0

謝謝,這是一個很大的改進。 – 2012-02-22 16:02:29

3

.each看起來會返回當它完成時環繞的對象。你將它分配給一個布爾值,它被強制爲true。你可能想用.every來完成你的任務。僅當每次迭代返回true時它才返回true,並且它在遇到第一個false時將停止循環。你可以找到更多的信息in the groovy docs

2

當您在閉包中返回,就好像方法中的一個方法調用中返回停止 - 這是局部的範圍和對於閉包被調用的實際方法沒有影響。在這種情況下,你可以使用其他方法之一(比如每個)或者使用常規的for循環,因爲它和Groovy的每一個工作方式一樣(也就是說,安全和支持,但不需要類型),但你可以打破循環或返回,因爲你在for循環真正的是它會從方法返回:

boolean checkLineageForTarget(Integer target, Collection<Node>stillToProcess){ 

    for (Node node in stillToProcess) { 
     Collection<Node> itsParents = getParentNodes(node) 
     ... 
    } 
    ... 
} 
相關問題