I haven't seen any programming language that has a simple function to break out of nested loops. I'm wondering:
Is there something at a low level making this impossible?
我还没有看到任何编程语言具有突破嵌套循环的简单功能。我想知道:有什么东西处于低水平使得这不可能吗?
Here is an example of what I mean (C#):
这是我的意思(C#)的一个例子:
while (true)
{
foreach (String s in myStrings)
{
break 2; // This would break out of both the foreach and while
}
}
Just break;
would be like break 1;
, and take you out of only the innermost loop.
刚刚休息就像打破1;,并带你走出最里面的循环。
Some languages have messy alternatives like goto
, which work but are not as elegant as the above proposed solution.
有些语言有像goto这样的混乱替代品,它们可以工作但不像上面提出的解决方案那样优雅。
4 个解决方案
#1
Perl does have something very similar to this feature. Instead of the number of nestings, you use a label much like goto
.
Perl确实有与此功能非常相似的东西。您可以使用与goto非常相似的标签,而不是嵌套的数量。
FOREVER:while (1) {
for my $string (@strings) {
last FOREVER;
}
}
The feature is intended to remove ambiguities when using loop controls in deeply nested loops. Using a label improves readability and it protects you should your level of nesting change. It reduces the amount of knowledge the inner loops have about the outer loops, though they still have knowledge.
该功能旨在消除在深层嵌套循环中使用循环控件时的歧义。使用标签可提高可读性,并在您的嵌套级别发生变化时保护您。尽管它们仍然具有知识,但它减少了内循环对外循环的知识量。
The nesting is also non-lexical, it will cross subroutine boundaries. This is where it gets weird and more goto-like.
嵌套也是非词法的,它将跨越子程序边界。这是它变得奇怪和更像goto的地方。
FOREVER:while (1) {
for my $string (@strings) {
do_something;
}
}
sub do_something {
last FOREVER;
}
This is not considered a good feature for all the reasons @Codor lays out in their answer. This sort of feature encourages very complex logic. You're nearly always better off restructuring deeply nested loops into multiple subroutine calls.
由于@Codor在答案中列出的所有原因,这不是一个好的功能。这种功能鼓励了非常复杂的逻辑。将深层嵌套循环重构为多个子例程调用几乎总是更好。
sub forever {
while (1) {
for my $string (@strings) {
return;
}
}
}
What you're asking for is, essentially, a restricted goto. It carries with it most of the same arguments for and against.
您要求的基本上是受限制的转到。它带有大多数支持和反对的相同论据。
while (1) {
for my $string (@strings) {
goto FOREVER;
}
}
FOREVER:print "I have escaped!\n"
The idea of saying "break out of the nth nested loop" is worse than a goto from a structural perspective. It means inner code has intimate knowledge of its surroundings. Should the nesting change, all of the inner loop controls may break. It creates a barrier to refactoring. For example, should you want to perform an extract method refactoring on the inner loop...
说“打破第n个嵌套循环”的想法比从结构角度来看更糟糕。这意味着内部代码对周围环境有深入的了解。如果嵌套发生变化,所有内部循环控件都可能会断开。它为重构创造了障碍。例如,您是否想要在内部循环上执行提取方法重构...
while (1) {
twiddle_strings(@strings);
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
Now the code controlling the outer loop is in a completely different function from the inner loop. What if the outer loop changes?
现在控制外循环的代码与内循环完全不同。如果外环改变怎么办?
while (1) {
while(wait_for_lock) {
twiddle_strings(@strings);
}
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
#2
No there's nothing on a low level that would prevent creating something like what you propose. And you also have a lot of languages implemented in a highlevel language that definitely would allow for this kind of behaviour.
没有什么可以阻止创建类似你提议的东西。而且你也有很多用高级语言实现的语言肯定会允许这种行为。
There are however several considerations when designing a language that would talk against this sort of construct, at least there is from my point of view.
然而,在设计一种与这种结构相对立的语言时,有几个注意事项,至少从我的角度来看是这样。
The main argument being that it opens up for a very complex structure in something that is probably allready overly complex. Nested loops are inherently hard to follow and figure out what is happening. If you'd add your construct it could make them even more complex.
主要论点是,它开辟了一个非常复杂的结构,可能已经过于复杂了。嵌套循环本质上很难遵循,并弄清楚发生了什么。如果你添加你的构造,它可能会使它们变得更加复杂。
Unless you consider a return
statement as a sort of break
of course :)
除非你认为退货声明当然是一种突破:)
#3
PHP has it since version 4. And IMHO it's not very good - it's quite easy to abuse it. Especially when you add levels to iterations or remove some or change code logic inside iterations. Code refactoring / optimization usually begins with iterations overview and trying to reduce cycles to conserve CPU usage. During this kind of optimization it's easy to miss a continue level and finding this kind of introduced bug is not an easy task if multiple people are working on a project.
从版本4开始,PHP就有它。而且恕我直言,它不是很好 - 滥用它很容易。特别是当您在迭代中添加级别或删除某些内容或更改迭代中的代码逻辑时。代码重构/优化通常从迭代概述开始,并尝试减少周期以节省CPU使用率。在这种优化过程中,很容易错过继续级别,如果有多个人正在处理项目,那么发现这种引入的错误并不是一件容易的事。
I'd prefer any time goto
since it's (usually) much safer. Unless you know exactly what you are doing. Also, goto
keeps BASIC in my mind.
我更喜欢任何时候转到,因为它(通常)更安全。除非你确切知道你在做什么。另外,goto将BASIC保留在我的脑海中。
#4
Although this is more speculation, there are some arguments both for and against such a possibility.
虽然这是更多的推测,但有一些论据支持和反对这种可能性。
Pro:
- Might be very elegant in some cases.
在某些情况下可能会非常优雅。
Con:
-
Might result in a tempation to write deeply nested loops, which is seen as undesirable by some.
可能导致写入深层嵌套循环的诱惑,这被某些人看作是不受欢迎的。
-
The desired behaviour can be implemented with
goto
.可以使用goto实现所需的行为。
-
The desired behaviour can be implemented with auxiliary variables.
可以使用辅助变量实现期望的行为。
-
Nested loops can in most cases be refactored to use just one loop.
在大多数情况下,嵌套循环可以重构为仅使用一个循环。
-
The desired behaviour can be implemented using exception handling (although, on the other hand, controlling the expected flow of execution is not the primary task of exception handling).
可以使用异常处理来实现所需的行为(另一方面,控制预期的执行流程不是异常处理的主要任务)。
That being said, I consider resposible usage of goto
to be legitimate.
话虽如此,我认为goto的合理使用是合法的。
#1
Perl does have something very similar to this feature. Instead of the number of nestings, you use a label much like goto
.
Perl确实有与此功能非常相似的东西。您可以使用与goto非常相似的标签,而不是嵌套的数量。
FOREVER:while (1) {
for my $string (@strings) {
last FOREVER;
}
}
The feature is intended to remove ambiguities when using loop controls in deeply nested loops. Using a label improves readability and it protects you should your level of nesting change. It reduces the amount of knowledge the inner loops have about the outer loops, though they still have knowledge.
该功能旨在消除在深层嵌套循环中使用循环控件时的歧义。使用标签可提高可读性,并在您的嵌套级别发生变化时保护您。尽管它们仍然具有知识,但它减少了内循环对外循环的知识量。
The nesting is also non-lexical, it will cross subroutine boundaries. This is where it gets weird and more goto-like.
嵌套也是非词法的,它将跨越子程序边界。这是它变得奇怪和更像goto的地方。
FOREVER:while (1) {
for my $string (@strings) {
do_something;
}
}
sub do_something {
last FOREVER;
}
This is not considered a good feature for all the reasons @Codor lays out in their answer. This sort of feature encourages very complex logic. You're nearly always better off restructuring deeply nested loops into multiple subroutine calls.
由于@Codor在答案中列出的所有原因,这不是一个好的功能。这种功能鼓励了非常复杂的逻辑。将深层嵌套循环重构为多个子例程调用几乎总是更好。
sub forever {
while (1) {
for my $string (@strings) {
return;
}
}
}
What you're asking for is, essentially, a restricted goto. It carries with it most of the same arguments for and against.
您要求的基本上是受限制的转到。它带有大多数支持和反对的相同论据。
while (1) {
for my $string (@strings) {
goto FOREVER;
}
}
FOREVER:print "I have escaped!\n"
The idea of saying "break out of the nth nested loop" is worse than a goto from a structural perspective. It means inner code has intimate knowledge of its surroundings. Should the nesting change, all of the inner loop controls may break. It creates a barrier to refactoring. For example, should you want to perform an extract method refactoring on the inner loop...
说“打破第n个嵌套循环”的想法比从结构角度来看更糟糕。这意味着内部代码对周围环境有深入的了解。如果嵌套发生变化,所有内部循环控件都可能会断开。它为重构创造了障碍。例如,您是否想要在内部循环上执行提取方法重构...
while (1) {
twiddle_strings(@strings);
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
Now the code controlling the outer loop is in a completely different function from the inner loop. What if the outer loop changes?
现在控制外循环的代码与内循环完全不同。如果外环改变怎么办?
while (1) {
while(wait_for_lock) {
twiddle_strings(@strings);
}
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
#2
No there's nothing on a low level that would prevent creating something like what you propose. And you also have a lot of languages implemented in a highlevel language that definitely would allow for this kind of behaviour.
没有什么可以阻止创建类似你提议的东西。而且你也有很多用高级语言实现的语言肯定会允许这种行为。
There are however several considerations when designing a language that would talk against this sort of construct, at least there is from my point of view.
然而,在设计一种与这种结构相对立的语言时,有几个注意事项,至少从我的角度来看是这样。
The main argument being that it opens up for a very complex structure in something that is probably allready overly complex. Nested loops are inherently hard to follow and figure out what is happening. If you'd add your construct it could make them even more complex.
主要论点是,它开辟了一个非常复杂的结构,可能已经过于复杂了。嵌套循环本质上很难遵循,并弄清楚发生了什么。如果你添加你的构造,它可能会使它们变得更加复杂。
Unless you consider a return
statement as a sort of break
of course :)
除非你认为退货声明当然是一种突破:)
#3
PHP has it since version 4. And IMHO it's not very good - it's quite easy to abuse it. Especially when you add levels to iterations or remove some or change code logic inside iterations. Code refactoring / optimization usually begins with iterations overview and trying to reduce cycles to conserve CPU usage. During this kind of optimization it's easy to miss a continue level and finding this kind of introduced bug is not an easy task if multiple people are working on a project.
从版本4开始,PHP就有它。而且恕我直言,它不是很好 - 滥用它很容易。特别是当您在迭代中添加级别或删除某些内容或更改迭代中的代码逻辑时。代码重构/优化通常从迭代概述开始,并尝试减少周期以节省CPU使用率。在这种优化过程中,很容易错过继续级别,如果有多个人正在处理项目,那么发现这种引入的错误并不是一件容易的事。
I'd prefer any time goto
since it's (usually) much safer. Unless you know exactly what you are doing. Also, goto
keeps BASIC in my mind.
我更喜欢任何时候转到,因为它(通常)更安全。除非你确切知道你在做什么。另外,goto将BASIC保留在我的脑海中。
#4
Although this is more speculation, there are some arguments both for and against such a possibility.
虽然这是更多的推测,但有一些论据支持和反对这种可能性。
Pro:
- Might be very elegant in some cases.
在某些情况下可能会非常优雅。
Con:
-
Might result in a tempation to write deeply nested loops, which is seen as undesirable by some.
可能导致写入深层嵌套循环的诱惑,这被某些人看作是不受欢迎的。
-
The desired behaviour can be implemented with
goto
.可以使用goto实现所需的行为。
-
The desired behaviour can be implemented with auxiliary variables.
可以使用辅助变量实现期望的行为。
-
Nested loops can in most cases be refactored to use just one loop.
在大多数情况下,嵌套循环可以重构为仅使用一个循环。
-
The desired behaviour can be implemented using exception handling (although, on the other hand, controlling the expected flow of execution is not the primary task of exception handling).
可以使用异常处理来实现所需的行为(另一方面,控制预期的执行流程不是异常处理的主要任务)。
That being said, I consider resposible usage of goto
to be legitimate.
话虽如此,我认为goto的合理使用是合法的。