English 中文(简体)
How can I get this snippet to work?
原标题:

I d like to port a little piece of code from Ruby to Groovy, and I m stuck at this:

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

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

Right now it dies with this message:

Exception thrown: Cannot compare ConsoleScript0$_run_closure1 with value ConsoleScript0$_run_closure1@1e6743e and java.lang.Integer with value 4 .

I tried to set the closure s delegate to be the array, but it seems that in the findAll method, it represents a closure, instead of an actual item from the array. I also tried to run the closure like this:

array.with {
   closure(array)
}

but I still wasn t able to make it work. Any thoughts on what could work? Ruby s equivalent would be to instance_eval the closure in the array s context.

EDIT: Running Mykola s code produced this output:

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

groovy.lang.GroovyRuntimeException: Cannot compare Demo$_main_closure1 with value  Demo$_main_closure1@fe53cf  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)

I m running Groovy 1.6.5.

问题回答

It looks like a bug for me. Here is the code

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()
   }
}

Which had to print (I tend to think) 4 as a size. And actually it prints if you will comment method size .

You can read about resolveStrategy more and then let us know what wasn t set properly.

Simple - you are trying to call a closure passing it an array, where findAll should be called on the array itself.

Here are a couple of possible solutions. First one is straightforward:

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

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

Or you can encapsulate findAll within a method body (that depends on what you are actually trying to do):

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

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

Here are the results of both:

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

Groove away!

In this case the delegate object is a java.util.ArrayList object which does not have a forEach method.

Nevertheless the Groovy wrapper for this class has this method, but it is not used here (this seams to be a bug).

You can workaround this by using delegate.forEach(). I can see that this breaks the DSL you have in mind, but maybe it takes you a step closer.

The following code works for me:

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

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

Try:

array.with(closure)

Or if you want to keep your syntax:

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




相关问题
Groovy - how to exit each loop?

I m new to Grails/Groovy and am trying to find a node in a an xml file; I ve figured out how to iterate over all of them, but I want to exit the loop when the target node is found. I ve read that ...

Eclipse Spring Builder set properties with Groovy beans

I typically use groovy to construct simple bean but the Spring IDE plugin to eclipse fails to build when I try to set a property that is generated by groovy without an explicit setter. For example, ...

How can I get this snippet to work?

I d like to port a little piece of code from Ruby to Groovy, and I m stuck at this: def given(array,closure) { closure.delegate = array closure() } given([1,2,3,4]) { findAll { it > 4} ...

Changing the value in a map in Groovy

This is about a very basic program I m writing in Groovy. I have defined a map inside a method: def addItem() { print("Enter the item name: ") def itemName = reader.readLine() print(...

Is functional Clojure or imperative Groovy more readable?

OK, no cheating now. No, really, take a minute or two and try this out. What does "positions" do? Edit: simplified according to cgrand s suggestion. (defn redux [[current next] flag] [(if flag ...

热门标签