如何从groovy闭包返回并停止其执行?
我想从闭包返回,就像在循环中使用break语句一样 例如:如何从groovy闭包返回并停止其执行?,groovy,closures,return,Groovy,Closures,Return,我想从闭包返回,就像在循环中使用break语句一样 例如: largeListOfElements.each{ element-> if(element == specificElement){ // do some work return // but this will only leave this iteration and start the next } } 在上面的if语句中,我希望停止遍历列表,并保留闭
largeListOfElements.each{ element->
if(element == specificElement){
// do some work
return // but this will only leave this iteration and start the next
}
}
在上面的if语句中,我希望停止遍历列表,并保留闭包以避免不必要的迭代
我见过一种在闭包内抛出异常并在闭包外捕获异常的解决方案,但我不太喜欢这种解决方案
除了更改代码以避免这种算法之外,还有其他解决方案吗 我认为你在错误的抽象层次上工作。
。每个
块完全按照它所说的做:它对每个元素执行一次闭包。您可能希望使用List.indexOf
来查找正确的specific元素
,然后对其执行所需的工作。我认为您希望使用find而不是每个元素(至少对于指定的示例而言)。闭包不直接支持break
实际上,groovy也没有为find使用闭包,而是使用for循环
或者,您可以编写自己的增强版本的find/each迭代器,该迭代器接受一个条件测试闭包,如果找到匹配项,则调用另一个闭包,如果满足匹配项,则中断该闭包
下面是一个例子:
Object.metaClass.eachBreak = { ifClosure, workClosure ->
for (Iterator iter = delegate.iterator(); iter.hasNext();) {
def value = iter.next()
if (ifClosure.call(value)) {
workClosure.call(value)
break
}
}
}
def a = ["foo", "bar", "baz", "qux"]
a.eachBreak( { it.startsWith("b") } ) {
println "working on $it"
}
// prints "working on bar"
Object.metaClass.eachBreak={ifClosure,workClosure->
for(迭代器iter=delegate.Iterator();iter.hasNext();){
def值=iter.next()
if(ifClosure.call(值)){
workClosure.call(值)
打破
}
}
}
DEFA=[“foo”、“bar”、“baz”、“qux”]
a、 eachBreak({it.startsWith(“b”)}){
println“处理$it”
}
//打印“在酒吧工作”
如果要处理所有元素直到找到特定元素,还可以执行以下操作:
largeListOfElements.find { element ->
// do some work
element == specificElement
}
尽管您可以将其用于任何类型的“中断条件”。
我只是使用它通过返回来处理集合的前n个元素
counter++ >= n
在闭包结束时。我理解groovy,缩短这类循环的方法是抛出一个用户定义的异常。我不知道语法会是什么(不是grrovy程序员),但是groovy在JVM上运行,所以它会像:
class ThisOne extends Exception {Object foo; ThisOne(Object foo) {this.foo=foo;}}
try { x.each{ if(it.isOk()) throw new ThisOne(it); false} }
catch(ThisOne x) { print x.foo + " is ok"; }
在paulmurray给出答案后,我自己也不确定如果在闭包中抛出异常会发生什么,因此我设计了一个JUnit测试用例,很容易思考:
class TestCaseForThrowingExceptionFromInsideClosure {
@Test
void testEearlyReturnViaException() {
try {
[ 'a', 'b', 'c', 'd' ].each {
System.out.println(it)
if (it == 'c') {
throw new Exception("Found c")
}
}
}
catch (Exception exe) {
System.out.println(exe.message)
}
}
}
上面的输出是:
a
b
c
Found c
但请记住,“不应将异常用于流控制”,请特别参阅此堆栈溢出问题:
因此,上述解决方案在任何情况下都不太理想。只需使用:
class TestCaseForThrowingExceptionFromInsideClosure {
@Test
void testEarlyReturnViaFind() {
def curSolution
[ 'a', 'b', 'c', 'd' ].find {
System.out.println(it)
curSolution = it
return (it == 'c') // if true is returned, find() stops
}
System.out.println("Found ${curSolution}")
}
}
上面的输出也是:
a
b
c
Found c
今天,我在处理每次关闭时都遇到了类似的问题。我想根据自己的情况打破执行流程,但做不到
在groovy中最简单的方法是,如果您希望根据某些条件返回布尔值,则在列表中使用any()而不是每个。Good ole
for
循环在groovy中仍然适用于您的用例
for (element in largeListOfElements) {
if(element == specificElement){
// do some work
return
}
}
OP对他想要的东西有点含糊不清:“在上面的if语句中,我希望停止遍历列表,留下闭包以避免不必要的迭代。”但我强烈怀疑你是对的!不仅如此,对于感兴趣的元素之前的元素,没有“做一些工作”注释。