动态创建 Groovy 闭包

Dynamically create Groovy closures

提问人:jeffery 提问时间:7/17/2023 更新时间:7/17/2023 访问量:52

问:

我需要动态创建闭包,这些闭包应该在自身内部调用其他闭包。

下面是我期望生成的代码执行的操作的示例

Closure execute = {
  println("First")
  Closure second = {
    println("Second")
    Closure third = {
      println("Third")
    }.call()
    println("Second")
  }.call()
  println("First")
}

execute.call()

以上结果为以下输出:

First
Second
Third
Second
First

如何根据以下列表动态创建上述闭包代码:

List<String> commands = ["First", "Second", "Third"]

任何指示表示赞赏。

Groovy 闭合 Jenkins-Groovy

评论


答:

2赞 tim_yates 7/17/2023 #1

因此,让我们制作一个返回闭包的函数

def wrap(String name, Closure cl = null) {
    { ->
        println(name)
        // If we were passed a closure, then run it and print the name again
        if (cl) {
            cl()
            println(name)
        }
    }
}

然后,获取我们的命令列表

List<String> commands = ["First", "Second", "Third"]

并将当前闭包存储在变量中

Closure current = null

然后,让我们向后浏览列表,创建一个新的闭包,并包装上一个闭包

commands.reverse().each {
    current = wrap(it, current)
}

然后我们可以运行最终闭包:

current()

我们得到输出:

First
Second
Third
Second
First

🎉

在非 jenkins groovy 中,您可以使用 inject 而不是带有 mutating 变量的 each:

Closure current = commands.reverse().inject(null) { curr, command ->
    wrap(command, curr)
}

但根据我回答 Jenkins 问题的经验,很少奏效,所以坚持第一种方法inject

评论

0赞 jeffery 7/17/2023
这对我有用。我很想知道以下块是做什么的?{ -> }
1赞 tim_yates 7/17/2023
{ -> }这是一个需要 0 个参数的闭包
0赞 dauer 7/17/2023 #2

您可以将闭包存储在变量中,并将这些变量存储在列表中

Closure first = {
    println("First")
}

Closure second = {
    println("Second")
}

Closure third = {
    println("Third")
    second()
}

List<Closure> execute = [first, second, third]

execute*.call()

输出:

First
Second
Third
Second