为什么Perl的foreach循环不需要使用my关键字声明变量?

12

今天,我在Perl中发现了一些我不知道的东西:它“本地化”了分配给迭代列表元素的变量。

当然,在Perl文档中有记录 - 但是我没有记住或阅读它。

下面的脚本演示了我的意思:

use warnings;
use strict;

my $g = 99;

foreach $g (1..5) {
  p($g);
}

sub p {
  my $l = shift;
  printf ("%2d %2d\n", $g, $l);
}

该脚本打印输出

99  1
99  2
99  3
99  4
99  5

因为$g被“局部化”到foreach循环中。

就我所知,如果我在foreach循环中添加了my来声明$g,则不会有任何区别:

foreach my $g (1..5) {

实际上,我最终这样做是因为它使得变量只在循环内部有效,从而让代码更加清晰易懂。

我的问题现在是:是否存在一种情况,在这种情况下我的使用my确实会有所不同(考虑到$g已经被全局声明)。


2
如果您已经在全局声明了变量,那么foreach循环就不需要再次声明。然而奇怪的是,它不会抱怨您重复声明了变量。例如,如果您删除范围,它将抱怨您已经声明了$g。我会去研究一下这个问题。 - user2082599
如果变量之前使用my声明过,它将使用该变量而不是全局变量,但仍然局限于循环。这种隐式本地化仅在foreach循环中发生。http://perldoc.perl.org/perlsyn.html#Foreach-Loops - user3606329
@user3606329 没错,但如果你删除范围,它将会产生一个错误。变量还没有进入循环,它是foreach语句的一部分。 - user2082599
1个回答

8
研究的行为在“perlsyn”中的“Foreach Loops”中有记录。
“foreach”循环遍历普通列表值,并将标量变量VAR依次设置为列表中的每个元素。如果变量前面带有关键字“my”,则它是词法作用域的,因此仅在循环内可见。
否则,变量隐式局部化到循环中,并在退出循环时恢复其原始值。如果以前使用“my”声明了变量,则使用该变量而不是全局变量,但仍将其局部化到循环中。
因此,在使用“my”进行本地化或将其留给“foreach”之间不应该有区别。
有趣的是,这种隐式本地化仅在“foreach”循环中发生。
所有这些都在“perlsub”的“通过“my()”实现私有变量”中进一步解释。
“foreach”循环默认动态地将其索引变量限定于作用域中的方式,类似于“local”。但是,如果索引变量以关键字“my”为前缀,或者作用域中已经有一个具有该名称的词汇,则会创建一个新的词汇。
由于在两种情况下都在内部创建了一个新的词汇,因此实际上没有任何差异。
我完全支持和推荐(始终)在那里使用“my”。

明白了。但我在这里看到的问题是$g还没有进入循环。所以如果在此之前没有声明和赋值$g,那么$g实际上是一个空值。 - user2082599
foreach my $i (1..4) { }中,$i的作用域被限制在循环范围内。它不存在于“之前”。如果没有my,并且在之前声明了$i,则只要看到它就会被限制在循环的作用域内。这就是上面引用所告诉我们的。 - zdim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接