在Perl中,在foreach循环中使用'my'会产生什么影响吗?无论是否使用'my',索引变量似乎始终是本地的。那么你可以在foreach循环中删除'my'并且仍然在循环体内有私有范围吗?
可以看出,使用'for'循环使用/不使用'my'之间存在差异:
use strict;
use warnings;
my ($x, $y) = ('INIT', 'INIT');
my $temp = 0;
for ($x = 1; $x < 10; $x++) {
$temp = $x+1;
}
print "This is x: $x\n"; # prints 'This is x: 10'.
for (my $y = 1; $y < 10; $y++) {
$temp = $y+1;
}
print "This is y: $y\n"; # prints 'This is y: INIT'.
但是对于foreach它似乎没有效果:
my ($i, $j) = ('INIT', 'INIT');
foreach $i (1..10){
$temp = $i+1;
}
print "\nThis is i: $i\n"; # prints 'This is i: INIT'.
foreach my $j (1..10){
$temp = $j+1;
}
print "\nThis is j: $j\n"; # prints 'This is j: INIT'.
答案 0 :(得分:14)
来自http://perldoc.perl.org/perlsyn.html#Foreach-Loops:
foreach循环遍历正常列表值并依次将变量VAR设置为列表的每个元素。如果变量前面带有关键字my,则它是词法范围的,因此仅在循环中可见。否则,该变量隐含在循环的本地,并在退出循环时重新获得其前一个值。如果先前使用my声明了变量,它将使用该变量而不是全局变量,但它仍然本地化为循环。这种隐式定位仅在foreach循环中发生。
答案 1 :(得分:11)
Hans链接到描述foreach
循环中的变量如何作用域的文档。区别是微妙的,但它可能很重要:
sub f { return $i }
$i = 4;
$m = $n = 0;
foreach $i (1 .. 10) { $m += f() }
foreach my $i (1 .. 10) { $n += f() }
print "Result with localization: $m\n"; # ==> 55
print "Result with lexical scoping: $n\n"; # ==> 40
答案 2 :(得分:1)
关于Perl我发现的最痛苦的发现之一是foreach循环上的“my”变量不是本地副本。我发现自己很沮丧地发现我的阵列被摧毁了。
唯一的方法似乎是:
foreach ( @array ) {
my $element = $_; # make a local copy
...
}
如果查看perldoc,它会说:“foreach循环索引变量是列表中您循环的每个项目的隐式别名”和“如果LIST的任何元素是左值,那么可以通过修改循环中的VAR来修改它。“
答案 3 :(得分:0)
我刚刚对这个有趣的问题做了一些额外的研究。
如果你做“我的$ y”,foreach并不在乎。在循环之前。迭代器仍将仅在范围内更改:my $y;
foreach $y (1..10) {}
$ y会在foreach范围内发生变化,但当它离开时,它会恢复到循环之前的状态。
我原以为或许foreach会自动执行“我的$ y”;在它开始运行之前,所以我尝试了严格的模式,但是这个解释没有削减它,因为它仍然要求:
foreach my $y (1..10) {}
而不是:
foreach $y (1..10) {}
......如果“foreach $ y”在功能上与“foreach my $ y”相同,则认为没有必要。
答案 4 :(得分:0)
foreach循环中的迭代器实际上是循环的本地。也就是说,它直接保存列表中的值,实际上是通过引用调用而不是按值。因此,如果在循环中操作值,它将更改列表中的值。但是,迭代器变量仅在引用循环时定义:
@names = qw(Kirk Spock Bones);
$officer = "Riker";
print "@names $officer\n"; # will print Kirk Spock Bones Riker
foreach $officer (@names) {
$officer .= "y";
}
print "@names $officer\n"; # will print Kirky Spocky Bonesy Riker
因此,迭代器(在本例中为$ officer)在保留foreach循环之前的任何值方面有效地以'my'开头。但是,如果更改的值已更改,则更改将传递回您正在迭代的列表。