4

假设我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
      }
    }
  }
}
4

3 回答 3

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

于 2016-01-23T18:07:41.623 回答
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被延迟评估的。

可迭代的coalesced属性返回另一个惰性可迭代,它跳过null原始中的所有值。

然后只需询问剩余可迭代的第一个值,这就是你的答案。

于 2016-01-25T07:15:10.943 回答
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;

在 everyfor的右括号之后。

(注意:理想情况下,被分配的变量——x在我的例子中,something在你的例子中——不需要是variable,因为它只分配了一次。但是,类型检查器目前无法证明这一点。)

它是如何工作的?如果该循环在没有else任何. 在这种情况下,我们也想要外循环;否则——也就是说,如果我们从内部循环中断——我们也想从外部循环中断。forbreakcontinuebreak

这可以使用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块和它之后的代码都需要一个副本。
于 2016-01-23T19:23:40.260 回答