【问题标题】:Groovy Global Closure not working in nested method callGroovy 全局闭包在嵌套方法调用中不起作用
【发布时间】:2013-08-05 19:05:42
【问题描述】:

我有一个简单的闭包,我希望能够在我的代码中使用它来测量任何其他闭包所需的时间。它看起来像这样:

def benchmark = {name,closure ->
    start = System.currentTimeMillis()
    ret =  closure.call()
    now = System.currentTimeMillis()   println(name + " took: " +  (now - start))
    ret
}

当它从同一个作用域调用时,它可以工作,如下所示:

benchmark('works') { println("Hello, World\n")}

但它在调用嵌套范围时似乎不起作用

def nested()
{
   benchmark('doesnt_work'){print("hello")}
}

nested()

【问题讨论】:

    标签: groovy scope closures


    【解决方案1】:

    那是因为你在脚本中运行它。

    Groovy 将上述转换为:

    class Script {
        def run() {
            def benchmark = {name,closure -> ...
            nested()
        }
    
        def nested() {
            benchmark('doesnt_work'){print("hello")}
        }
    }
    

    如您所见,闭包是隐式run 方法的局部变量,但nested 方法属于该类...

    我相信你有 3 个选择:

    1. nested设为闭包,它们都将存在于同一个作用域中

      def benchmark = {name,closure ->
          start = System.currentTimeMillis()
          ret =  closure.call()
          now = System.currentTimeMillis()
          println(name + " took: " +  (now - start))
          ret
      }
      
      def nested = {
         benchmark('doesnt_work'){print("hello")}
      }
      
      nested()
      
    2. 编写一个适当的类并自己控制范围

      class Test {
          def benchmark = {name,closure ->
              long start = System.currentTimeMillis()
              def ret =  closure.call()
              long now = System.currentTimeMillis()
              println(name + " took: " +  (now - start))
              ret
          }
      
          def nested() {
              benchmark('doesnt_work'){print("hello")}
          }
      
          static main( args ) {
              new Test().nested()
          }
      }
      
    3. def benchmark = {name,closure -> ... 之前添加@groovy.transform.Field 这会将闭包定义向上移动为property of this Script class

      @groovy.transform.Field def benchmark = { name, closure ->
          start = System.currentTimeMillis()
          ret =  closure.call()
          now = System.currentTimeMillis()
          println(name + " took: " +  (now - start))
          ret
      }
      
      def nested() {
         benchmark('doesnt_work'){print("hello")}
      }
      
      nested()
      

    【讨论】:

    • 使用了 Field 选项,因为它不会以其他方式干扰脚本流
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 2023-03-26
    • 2021-12-15
    相关资源
    最近更新 更多