我刚开始学习Perl,发现自己因以下代码块的结果而受阻:
@x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
foreach (@x) {
$x = pop (@x) ;
$y = shift (@x);
print ("$x $y \n");
}
Run Code Online (Sandbox Code Playgroud)
输出是:
10 1
9 2
8 3
7 4
Run Code Online (Sandbox Code Playgroud)
我曾预料到另一条线:6 5.为什么没有这样的线?是因为在打印的迭代之后7 4,数组中剩余的元素数量等于已经完成的迭代次数,因此就Perl而言,循环完成了吗?
您可能不应该在迭代期间修改列表.来自perldoc perlsyn:
如果
LIST是数组的任何部分,foreach如果在循环体内添加或删除元素,将会非常困惑,例如splice.所以不要这样做.
如果你$_在循环(print ("$x $y $_\n");)期间打印出来,你可以看到发生了什么:
10 1 1
9 2 3
8 3 5
7 4 7
Run Code Online (Sandbox Code Playgroud)
在这种情况下,Perl只是维护一个索引,它通过数组递增.由于您从头开始删除元素,因此索引在第四次迭代结束时从修改后的数组的末尾开始,因此foreach循环终止.
小智 7
这可以很好地说明当您更改要迭代的数组时会发生什么.
尝试:
use strict: #Always!
use warnings; #Always!
my @x = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
my $n=$#x;
foreach my $i(0..$n) {
my $x = pop (@x) ;
my $y = shift (@x);
print "$x $y\n" if defined $x and defined $y;
}
Run Code Online (Sandbox Code Playgroud)
或者,更好的是:
use strict;
use warnings;
my @x=1..10; #same thing, just written more idiomatically
while(@x)
{
my $x=pop @x; #no parentheses needed
my $y=shift @x;
print "$x $y\n";
}
Run Code Online (Sandbox Code Playgroud)
注意在while上面的循环中,数组在标量上下文中@x被解释,因此while循环将继续,直到元素的数量@x为零.