我遇到了在双嵌套while
循环中突破最里面的封闭循环的问题。
考虑:
use v5.14;
my $i=0;
while ($i<=1) {
my $j=0;
do {
last if $j==2;
say $j++;
} while ($j<4);
$i++;
}
输出在这里:
0
1
而预期的输出应为:
0
1
0
1
在最里面的封闭循环中添加标签:
my $i=0;
while ($i<=1) {
my $j=0;
LINE: do {
last LINE if $j==2;
say $j++;
} while ($j<4);
$i++;
}
给出错误:
Label not found for "last LINE" at ./p.pl line 9.
答案 0 :(得分:8)
您只能在使用last
的循环中使用next
,redo
和BLOCK
。
while (EXPR) BLOCK
until (EXPR) BLOCK
for (LIST) BLOCK
for (EXPR; EXPR; EXPR) BLOCK
BLOCK
您不能在语句修饰符 [1] 创建的循环上使用它们。
EXPR while EXPR;
EXPR until EXPR;
do BLOCK while EXPR;
只是EXPR while EXPR;
的一个案例。该循环没有BLOCK
last
可供使用。它只是一个while
语句修饰符,它正在修改do
函数 [2] 。正在修改的do
函数有BLOCK
,但do
不是循环。
您可以向last
添加一个循环,例如通常只执行一次的裸循环(BLOCK
)。
my $i=0;
while ($i<=1) {
LOOP: {
my $j=0;
do {
last if $j==2;
say $j++;
} while ($j<4);
}
++$i;
}
但如果我们能确保++$i
总是被执行,我们就可以next
外部循环。
my $i=0;
while ($i<=1) {
my $j=0;
do {
next if $j==2;
say $j++;
} while ($j<4);
} continue {
++$i;
}
以上简化为
for (my $i=0; $i<=1; ++$i) {
my $j=0;
do {
next if $j==2;
say $j++;
} while ($j<4);
}
简化为
for my $i (0..1) {
my $j=0;
do {
next if $j==2;
say $j++;
} while ($j<4);
}
当然,这假设我们需要保留do while
。如果没有,我们可以写
for my $i (0..1) {
for my $j (0..3) {
last if $j==2;
say $j;
}
}
或者我想。事实证明它适用于for
!!!!
>perl -we"print($_), (($_ == 5) && last) for 1..10; print(qq{\ndone\n});"
12345
done
嗯,不是“仅仅”。它特别容易进行底部测试,而不是经过顶级测试。
答案 1 :(得分:3)
正如perldoc do
所有人都已说过:
关于这一点的更深层次的部落知识是你应该为单行或最多两行声明保留这些语句修饰符。
如果你想要一个多线程块是一个循环,编码器应该能够从第一行观察到。因此,不要使用带有do BLOCK
的语句修饰符,而是设置一个无限循环并创建测试以在最后突破它:
while (1) {
...
last if EXPR;
}
这会将你有点人为的例子改为:
use v5.14;
my $i = 0;
while ($i <= 1) {
my $j = 0;
while (1) {
last if $j == 2;
say $j++;
last if $j >= 4;
}
$i++;
}
答案 2 :(得分:2)
您无法在last
块中使用do{}
,但您可以
my $i=0;
while ($i<=1) {
my $j=0;
LINE: {
do {
last LINE if $j==2;
say $j++;
} while ($j<4);
}
$i++;
}
或
my $i=0;
OUTER: while ($i<=1) {
my $j=0;
LINE: do {
next OUTER if $j==2;
say $j++;
} while ($j<4);
}
continue {
$i++;
}
答案 3 :(得分:1)
如果你真的必须:
my $i=0;
while ($i++<=1) {
my $j=0;
LINE: {
do {
last LINE if $j==2;
say $j++;
} while ($j<4);
}
}
答案 4 :(得分:1)
正如其他人所说,您不能将last
与do
:
执行BLOCK不算作循环,因此循环控制语句next,last或redo不能用于离开或重启块。
另一种解决方案是使用另一个while
循环:
my $i = 0;
while ($i <= 1) {
my $j = 0;
while($j < 4) {
last if $j == 2;
say $j++;
}
$i++;
}
或使用for
循环:
for my $i (0 .. 1) {
for my $j (0 .. 3) {
last if $j == 2;
say $j;
}
}