让我说我在锡兰有几个嵌套的for
循环。如何摆脱所有循环:
variable Integer? something = null;
for (i in 0:3) {
for (j in 0:3) {
for (k in 0:3) {
something = someFunction(i,j,k);
if (something exists) {
// break out of everything, we found it
}
}
}
}
答案 0 :(得分:6)
这样做的一种方法是将整个事物包装在一个闭包中,然后在想要突破所有内容时使用return调用它:
Integer? doLoops() {
for (i in 0:3) {
for (j in 0:3) {
for (k in 0:3) {
Integer? something = someFunction(i,j,k);
if (something exists) {
return something;
}
}
}
}
return null;
}
Integer? something = doLoops();
因为Ceylon支持闭包,所以您还可以在定义doLoops
的范围内读取和写入函数外的其他值。
答案 1 :(得分:5)
您可以改为使用理解和流处理语法:
Iterable<Integer?> stream = {
for (i in 0:3) for (j in 0:3) for (k in 0:3) someFunction(i,j,k)
};
Integer? = stream.coalesced.first;
这将按预期工作,因为{ for ... }
理解会创建一个懒惰评估的Iterable
。
iterable的coalesced
属性返回另一个lazy iterable,它跳过原始中的所有null
值。
然后只要求剩下的可迭代的第一个值,那就是你的答案。
答案 2 :(得分:3)
另一种方法是在else
循环上使用for
块:
shared void run() {
variable Integer? x = null;
for (i in 0:3) {
for (j in 0:3) {
for (k in 0:3) {
value n = i*j*k;
if (n > 18) {
x = n;
break;
} else {
continue;
}
} else {
continue;
}
break;
} else {
continue;
}
break;
} else {
x = null;
}
print(x);
}
一般来说,放置
else {
continue;
}
break;
在每个for
的结束后。
(注意:理想情况下,我的示例中指定的变量x
,您自己的something
- 不需要variable
,因为它只分配了一次。但是, typechecker目前can’t prove that。)
它是如何工作的?如果该循环在没有任何else
的情况下运行完成,则执行for
循环后的break
。在这种情况下,我们也希望continue
外部循环;否则 - 也就是说,如果我们从内循环中断开 - 我们也希望从外部循环中break
。
使用ceylon/ceylon#3223中提出的以下语法可以更简洁地编写:
for (a in b) {
for (x in y) {
if (something) {
break;
}
} then { // opposite of else: runs iff there was a break in the inner loop
break;
}
}
我不建议使用此解决方案,原因有三:
for {} else {}
功能相当模糊,如果您不熟悉它,其含义并不明显,使得代码对于随意的读者来说难以理解。else
块和它之后的代码都需要副本。