2009-11-15 99 views
0

我想端口一小段代碼從紅寶石到Groovy和我被困在此:我怎樣才能得到這個片段的工作?

def given(array,closure) { 
    closure.delegate = array 
    closure() 
} 

given([1,2,3,4]) { 
    findAll { it > 4} 
} 

現在死了此消息:

Exception thrown: Cannot compare ConsoleScript0$_run_closure1 with value '[email protected]' and java.lang.Integer with value '4'

我試圖將閉包的委託設置爲數組,但似乎在findAll方法中,它表示閉包,而不是數組中的實際項目。我也試圖運行這樣的關閉:

array.with { 
    closure(array) 
} 

但我仍然無法使它的工作。有什麼想法可以工作? Ruby的等價物將是instance_eval數組上下文中的閉包。

編輯:運行尼古拉的代碼生成的輸出:

given [1, 2, 3, 4] 
class Demo$_main_closure1 
2 
Exception thrown: Cannot compare Demo$_main_closure1 with value '[email protected]' and java.lang.Integer with value '2' 

groovy.lang.GroovyRuntimeException: Cannot compare Demo$_main_closure1 with value '[email protected]' and java.lang.Integer with value '2' 

    at Demo$_main_closure1_closure2.doCall(ConsoleScript3:15) 

    at Demo$_main_closure1.doCall(ConsoleScript3:15) 

    at Demo$_main_closure1.doCall(ConsoleScript3) 

    at Demo.given(ConsoleScript3:28) 

    at Demo$given.callStatic(Unknown Source) 

    at Demo.main(ConsoleScript3:12) 

我跑的Groovy 1.6.5。

回答

1

它看起來像一個bug。這裏是代碼

class Demo { 
    static def main(args) { 
     given([1, 2, 3, 4]) { 
      println getClass() 
      println size() 
      grep { v -> v > 2 } 
     } 
    } 

    static def size() { 
     return 2 
    } 

    static def given(object, closure) { 
     println 'given ' + object 

     closure.resolveStrategy = Closure.DELEGATE_ONLY 
     closure.delegate = object 
     closure() 
    } 
} 

哪些不得不打印(我傾向於認爲)'4'作爲一個大小。而且實際上它會打印,如果你會評論方法'大小'。

您可以閱讀關於resolveStrategy的更多信息,然後讓我們知道什麼設置不正確。

+0

我已經更新了我的問題與輸出你的代碼。仍然不起作用。 – Geo 2009-11-15 18:58:46

+0

是的。這就是我正在談論的。要麼我不明白'DELEGATE_ONLY'選項,或者1.6.5中存在錯誤。我明天將在工作中嘗試1.6.4。 – 2009-11-15 19:32:15

+0

謝謝!請在有機會之後回覆。 – Geo 2009-11-15 19:50:02

1

簡單 - 你正試圖調用一個封閉傳遞給它一個數組,其中findAll應該被稱爲該數組本身。

這裏有幾個可能的解決方案。第一個是簡單的:

def given(array,closure) { 
    closure(array) 
} 

println "first way result: " + 
given ([1,2,3,4,5]) { it.findAll { it > 4 } } 

或者你也可以在方法體中封裝findAll(取決於你實際上是試圖做):

def given(array,closure) { 
array.findAll(closure) 
} 

println "second way result: " + 
given([1,2,3,4,5]) { it > 4 } 

這裏有兩種結果:

first way result: [5] 
second way result: [5] 

溝槽!

+0

我知道這是可能的。我想讓我的工作方式。 – Geo 2009-11-15 20:43:04

1

在這種情況下,委託對象是一個沒有forEach方法的java.util.ArrayList對象。

儘管如此,這個類的Groovy包裝有這種方法,但這裏沒有使用它(這個接縫是一個bug)。

您可以使用delegate.forEach()解決此問題。我可以看到,這打破了你心中的DSL,但也許它會讓你更靠近一步。

下面的代碼對我的作品:

def given(array,closure) { 
    closure.delegate = array 
    closure() 
} 

given([1,2,3,4]) { 
    delegate.findAll { it > 4} 
} 
0

嘗試:

array.with(closure) 

或者,如果你想保持你的語法:

def given(array,closure) { 
    array.with(closure) 
} 
相關問題