在Groovy中实现do ... while的优雅方法

67
7个回答

65

你可以自己编写循环来满足你的需求。下面是一个使用loop { code } until { condition }的示例。由于while是一个关键字,所以你无法使用对应的loop { code } while { condition }。但你可以给它取别的名字。

无论如何,这里有一些简单粗暴的代码用于循环直到某个条件满足。唯一要注意的是,你需要使用大括号将until条件包装成闭包。可能还有其他问题。

class Looper {
   private Closure code

   static Looper loop( Closure code ) {
      new Looper(code:code)
   }

   void until( Closure test ) {
      code()
      while (!test()) {
         code()
      }
   }
}

使用方法:

import static Looper.*

int i = 0
loop {
   println("Looping : "  + i)
   i += 1
} until { i == 5 }

无法理解使用的代码,您能详细说明一下吗?我的理解是循环后面的所有内容都被视为闭包,那么直到什么时候才会被调用呢? - Rao
3
把它看作是 loop({...}).until({...})。因此,在 loop() 的返回值上调用 until()。Groovy 命令表达式意味着您可以省略 until() 前面的 . - Peter Ledbrook
@PeterLedbrook,非常感谢您的解释。现在很清楚了。 - Rao

38
这是Groovy中最接近纯语言语法的do-while循环。
while ({
    x.doIt()
    !x.isFinished()
}()) continue

在花括号内的最后一个语句(在闭包内)被评估为循环退出条件。
可以使用分号代替continue关键字。
另一个好处是,循环可以进行参数化(类似于):
Closure<Boolean> somethingToDo = { foo ->
    foo.doIt()
    !foo.isFinished()
}

然后在其他地方:
while (somethingToDo(x)) continue

以前我在这里提出了这个答案:如何使用Groovy迭代InputStream中的所有字节,考虑到它缺少do-while语句?

2
它有相当令人不幸的括号和大括号,但它是最优雅的方式,没有任何重复。 - topr
1
虽然我喜欢这个解决方案的优雅和巧妙,但我对其可读性并不满意。我可以想象自己在一年后回到这段代码时会想“这里发生了什么”。我还没有决定,因为我也不喜欢重复。 - rudolfson

30

1
蒂姆的第二个选项(在“或”之后)- 还有什么比这更标准的休息方式呢? - JoeG
2
经过仔细考虑,我认为第二个选项更简单、更好。 - MariuszS

10

更新:Groovy 2.6已被放弃,集中精力开发3.0版本。

从Groovy 2.6开始,在启用新的Parrot解析器时支持do-while,而从Groovy 3.0开始,则是默认支持。请参见发行说明

// classic Java-style do..while loop
def count = 5
def fact = 1
do {
    fact *= count--
} while(count > 1)
assert fact == 120

1
太遗憾了,Groovy 2.6 被放弃了...我不建议人们使用永远不会发布的 2.6 beta 版本。 - Alex White
2
你说得对,感谢评论,我已经更新了答案! - Mene

10

您可以使用条件变量与常规 while 循环:

def keepGoing = true
while( keepGoing ){
    doSomething()
    keepGoing = ... // evaluate the loop condition here
}

3

到目前为止,Groovy已经支持do/while

do {

  x.doIt()

} while (!x.isFinished())

1
您可以以更加优雅的方式在Groovy中实现它:
def loop(Closure g){
    def valueHolder = [:]
    g.delegate = valueHolder
    g.resolveStrategy = Closure.DELEGATE_FIRST
    g()
    [until:{Closure w ->
        w.delegate = valueHolder
        w.resolveStrategy = Closure.DELEGATE_FIRST
        while(!w()){
        g()
        }
        }]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接