【问题标题】:How can I get this snippet to work?我怎样才能让这个片段工作?
【发布时间】:2009-11-15 18:04:15
【问题描述】:

我想将一小段代码从 Ruby 移植到 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 'ConsoleScript0$_run_closure1@1e6743e' and java.lang.Integer with value '4'.

我尝试将闭包的委托设置为数组,但似乎在findAll 方法中,它表示一个闭包,而不是数组中的实际项。我也尝试像这样运行闭包:

array.with {
   closure(array)
}

但我仍然无法让它工作。关于什么可以起作用的任何想法? Ruby 的等价物是 instance_eval 数组上下文中的闭包。

编辑:运行 Mykola 的代码会产生以下输出:

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)

我正在运行 Groovy 1.6.5。

【问题讨论】:

    标签: groovy metaprogramming eval porting


    【解决方案1】:

    对我来说这似乎是一个错误。这是代码

    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 的更多信息,然后让我们知道哪些设置不正确。

    【讨论】:

    • 我已经用您的代码输出更新了我的问题。还是不行。
    • 是的。这就是我所说的。要么我不理解 'DELEGATE_ONLY' 选项,要么 1.6.5 中存在错误。我明天上班试试 1.6.4。
    • 谢谢!有机会后请回帖。
    • 根据groovy.codehaus.org/api/groovy/lang/…,解析策略仅适用于属性。由于 grep findAll 等是设置 resolveStrategy 属性的方法并不能解决问题。
    • 解析策略不仅适用于属性,否则在闭包中调用“println size()”将不起作用,但它确实有效。这是一个 groovy 错误,应该在其上打开 JIRA 票证。 def given(array,closure) { closure.resolveStrategy = Closure.DELEGATE_FIRSTclosure.delegate = array closure() } given([1,2,3,4,5]) { assert 5 == size() assert [5] == findAll { 它 > 4} }
    【解决方案2】:

    简单 - 你试图调用一个闭包,传递给它一个数组,findAll 应该被称为 on 数组本身。

    这里有几个可能的解决方案。第一个很简单:

    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]
    

    滚开!

    【讨论】:

      【解决方案3】:

      在这种情况下,委托对象是一个没有 forEach 方法的 java.util.ArrayList 对象。

      尽管如此,这个类的 Groovy 包装器有这个方法,但这里没有使用它(这似乎是一个错误)。

      您可以使用delegate.forEach() 解决此问题。我可以看到这打破了你所想的 DSL,但也许它会让你更近一步。

      以下代码适用于我:

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

      【讨论】:

        【解决方案4】:

        试试:

        array.with(closure)
        

        或者如果你想保留你的语法:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多