为什么 most/all 种语言没有多循环中断功能?
Why do most/all languages not have a multi-loop break function?
我还没有看到任何编程语言具有简单的功能来跳出嵌套循环。我在想:
有什么低层次的东西使这不可能吗?
这是我的意思的示例 (C#):
while (true)
{
foreach (String s in myStrings)
{
break 2; // This would break out of both the foreach and while
}
}
只是 break;
会像 break 1;
,并且只会让您跳出最内层的循环。
有些语言有像 goto
这样的混乱替代方案,它们可以工作但不如上面提出的解决方案那么优雅。
虽然这是更多的猜测,但也有一些论据支持和反对这种可能性。
临:
- 在某些情况下可能非常优雅。
缺点:
可能会产生编写深度嵌套循环的冲动,这在某些人看来是不受欢迎的。
可以使用 goto
.
实现所需的行为
可以使用辅助变量实现所需的行为。
在大多数情况下,嵌套循环可以重构为只使用一个循环。
可以使用异常处理来实现所需的行为(尽管另一方面,控制预期的执行流程并不是异常处理的主要任务)。
话虽如此,我认为 goto
的合理使用是合法的。
不,在低级别上没有任何东西可以阻止创建像您所提议的那样的东西。而且你还有很多用高级语言实现的语言,肯定会允许这种行为。
然而,在设计一种会反对这种结构的语言时,有几个考虑因素,至少从我的角度来看是这样。
主要论点是它在可能已经过于复杂的事物中打开了一个非常复杂的结构。嵌套循环本质上很难理解和弄清楚发生了什么。
如果你要添加你的构造,它可能会使它们更加复杂。
当然,除非您将 return
语句视为一种 break
:)
Perl 确实有一些与此功能非常相似的东西。而不是嵌套数,you use a label much like goto
.
FOREVER:while (1) {
for my $string (@strings) {
last FOREVER;
}
}
该功能旨在消除在深层嵌套循环中使用循环控件时的歧义。使用标签可以提高可读性,并在嵌套级别发生变化时保护您。它减少了内部循环对外部循环的了解,尽管它们仍然有知识。
嵌套也是非词法的,它会跨越子程序边界。这就是它变得奇怪和更像 goto 的地方。
FOREVER:while (1) {
for my $string (@strings) {
do_something;
}
}
sub do_something {
last FOREVER;
}
由于种种原因,这不是一个好功能 。这种特性鼓励非常复杂的逻辑。将深度嵌套的循环重组为多个子例程调用几乎总是更好。
sub forever {
while (1) {
for my $string (@strings) {
return;
}
}
}
本质上,您要求的是一个受限的 goto。它带有大多数相同的支持和反对论据。
while (1) {
for my $string (@strings) {
goto FOREVER;
}
}
FOREVER:print "I have escaped!\n"
从结构的角度来看,说 "break out of the nth nested loop" 的想法比 goto 更糟糕。这意味着内部代码对其周围环境有深入的了解。如果嵌套发生变化,所有内部循环控件都可能中断。它为重构制造了障碍。例如,如果您想在内循环中执行 extract method refactoring...
while (1) {
twiddle_strings(@strings);
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
现在控制外循环的代码与内循环完全不同。如果外循环发生变化怎么办?
while (1) {
while(wait_for_lock) {
twiddle_strings(@strings);
}
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
PHP has it 从版本 4 开始。而且恕我直言,它不是很好 - 很容易滥用它。特别是当您向迭代中添加级别或删除某些级别或更改迭代内的代码逻辑时。代码重构/优化通常从迭代概述开始,并尝试减少周期以节省 CPU 使用。在这种优化过程中很容易漏掉一个continue level,如果多人一起做一个项目,发现这种引入的bug不是一件容易的事。
我更愿意随时 goto
因为它(通常)更安全。除非你确切地知道你在做什么。此外,goto
将 BASIC 牢记在心。
我还没有看到任何编程语言具有简单的功能来跳出嵌套循环。我在想:
有什么低层次的东西使这不可能吗?
这是我的意思的示例 (C#):
while (true)
{
foreach (String s in myStrings)
{
break 2; // This would break out of both the foreach and while
}
}
只是 break;
会像 break 1;
,并且只会让您跳出最内层的循环。
有些语言有像 goto
这样的混乱替代方案,它们可以工作但不如上面提出的解决方案那么优雅。
虽然这是更多的猜测,但也有一些论据支持和反对这种可能性。
临:
- 在某些情况下可能非常优雅。
缺点:
可能会产生编写深度嵌套循环的冲动,这在某些人看来是不受欢迎的。
可以使用
goto
. 实现所需的行为
可以使用辅助变量实现所需的行为。
在大多数情况下,嵌套循环可以重构为只使用一个循环。
可以使用异常处理来实现所需的行为(尽管另一方面,控制预期的执行流程并不是异常处理的主要任务)。
话虽如此,我认为 goto
的合理使用是合法的。
不,在低级别上没有任何东西可以阻止创建像您所提议的那样的东西。而且你还有很多用高级语言实现的语言,肯定会允许这种行为。
然而,在设计一种会反对这种结构的语言时,有几个考虑因素,至少从我的角度来看是这样。
主要论点是它在可能已经过于复杂的事物中打开了一个非常复杂的结构。嵌套循环本质上很难理解和弄清楚发生了什么。 如果你要添加你的构造,它可能会使它们更加复杂。
当然,除非您将 return
语句视为一种 break
:)
Perl 确实有一些与此功能非常相似的东西。而不是嵌套数,you use a label much like goto
.
FOREVER:while (1) {
for my $string (@strings) {
last FOREVER;
}
}
该功能旨在消除在深层嵌套循环中使用循环控件时的歧义。使用标签可以提高可读性,并在嵌套级别发生变化时保护您。它减少了内部循环对外部循环的了解,尽管它们仍然有知识。
嵌套也是非词法的,它会跨越子程序边界。这就是它变得奇怪和更像 goto 的地方。
FOREVER:while (1) {
for my $string (@strings) {
do_something;
}
}
sub do_something {
last FOREVER;
}
由于种种原因,这不是一个好功能
sub forever {
while (1) {
for my $string (@strings) {
return;
}
}
}
本质上,您要求的是一个受限的 goto。它带有大多数相同的支持和反对论据。
while (1) {
for my $string (@strings) {
goto FOREVER;
}
}
FOREVER:print "I have escaped!\n"
从结构的角度来看,说 "break out of the nth nested loop" 的想法比 goto 更糟糕。这意味着内部代码对其周围环境有深入的了解。如果嵌套发生变化,所有内部循环控件都可能中断。它为重构制造了障碍。例如,如果您想在内循环中执行 extract method refactoring...
while (1) {
twiddle_strings(@strings);
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
现在控制外循环的代码与内循环完全不同。如果外循环发生变化怎么办?
while (1) {
while(wait_for_lock) {
twiddle_strings(@strings);
}
}
sub twiddle_strings {
for my $string (@strings) {
last 2;
}
}
PHP has it 从版本 4 开始。而且恕我直言,它不是很好 - 很容易滥用它。特别是当您向迭代中添加级别或删除某些级别或更改迭代内的代码逻辑时。代码重构/优化通常从迭代概述开始,并尝试减少周期以节省 CPU 使用。在这种优化过程中很容易漏掉一个continue level,如果多人一起做一个项目,发现这种引入的bug不是一件容易的事。
我更愿意随时 goto
因为它(通常)更安全。除非你确切地知道你在做什么。此外,goto
将 BASIC 牢记在心。