动态创建Groovy闭包

huangapple go评论65阅读模式
英文:

Dynamically create Groovy closures

问题

以下是根据您提供的代码示例和列表创建动态闭包代码的翻译部分:

// 创建一个执行闭包
Closure execute = {
  println("First")
  // 遍历命令列表,并为每个命令创建闭包并调用
  List<String> commands = ["First", "Second", "Third"]
  commands.each { command ->
    Closure closure = {
      println(command)
    }
    closure.call()
  }
  println("First")
}

// 调用执行闭包
execute.call()

请注意,这段代码在Groovy语言中编写,用于动态创建闭包并根据命令列表调用它们。不包括代码的其他部分。

如果您需要更多帮助或有其他问题,请随时提出。

英文:

I have the need to dynamically create closures which should call other closures within itself.

Here is an example of what I expect the resulting code to do

Closure execute = {
  println(&quot;First&quot;)
  Closure second = {
    println(&quot;Second&quot;)
    Closure third = {
      println(&quot;Third&quot;)
    }.call()
    println(&quot;Second&quot;)
  }.call()
  println(&quot;First&quot;)
}

execute.call()

The above results in the following output:

First
Second
Third
Second
First

How can I create the above closure code dynamically given the following list:

List&lt;String&gt; commands = [&quot;First&quot;, &quot;Second&quot;, &quot;Third&quot;]

Any pointers appreciated.

答案1

得分: 2

以下是翻译好的部分:

所以,让我们创建一个返回闭包的函数:

def wrap(String name, Closure cl = null) {
    { ->
        println(name)
        // 如果传递了一个闭包,就执行它并再次打印名称
        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 代替带有变异变量的 each

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

但根据我回答 Jenkins 问题的经验,inject 很少有效,所以请坚持使用第一种方式。

英文:

So, lets make a function which returns a closure

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

Then, take our list of commands

List&lt;String&gt; commands = [&quot;First&quot;, &quot;Second&quot;, &quot;Third&quot;]

And store the current closure in a variable

Closure current = null

Then, lets go backwards through the list, creating a new closure, and wrapping the previous one

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

Then we can run the final closure:

current()

And we get the output:

First
Second
Third
Second
First

🎉

In non-jenkins groovy you can use inject instead of the each with a mutating variable:

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

But in my experience of answering Jenkins questions, inject rarely works, so stick with the first way

答案2

得分: 0

你可以将闭包存储在变量中,然后将这些变量存储在列表中。

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
英文:

You can store closures in variables and store those variables in a list

Closure first = {
    println(&quot;First&quot;)
}

Closure second = {
    println(&quot;Second&quot;)
}

Closure third = {
    println(&quot;Third&quot;)
    second()
}

List&lt;Closure&gt; execute = [first, second, third]

execute*.call()

Output:

First
Second
Third
Second

huangapple
  • 本文由 发表于 2023年7月17日 20:08:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76704307.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定