【问题标题】:Why doesn't Perl's foreach require its variable to be declared with my?为什么 Perl 的 foreach 不需要用 my 声明它的变量?
【发布时间】:2019-06-06 16:32:27
【问题描述】:

今天,我在 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 已在全球范围内声明)。

【问题讨论】:

  • 如果你有全局声明,foreach 不需要 my 声明。然而奇怪的是它不会抱怨你再次声明它。例如,如果您删除范围,它会抱怨您已经声明了$g,我会去研究一下。
  • 如果该变量以前用 my 声明过,它会使用该变量而不是全局变量,但它仍被本地化到循环中。此隐式本地化仅发生在 foreach 循环中perldoc.perl.org/perlsyn.html#Foreach-Loops
  • @user3606329 这是正确的,但是如果您使用该代码并删除范围,则会产生错误。该变量尚未进入循环,它是 foreach 语句的一部分。

标签: perl variables foreach local-variables


【解决方案1】:

调查的行为记录在Foreach Loops in perlsyn

foreach 循环遍历一个普通的列表值,并将标量变量 VAR 依次设置为列表的每个元素。如果变量以关键字my 开头,则它是词法范围的,因此仅在循环内可见。

继续解释

否则,该变量隐式地位于循环的局部,并在退出循环时恢复其先前的值。如果该变量先前已用my 声明,则它使用该变量而不是全局变量,但它仍被本地化为循环。

因此,将其本地化为 my 或将其留给 foreach 应该没有区别。

有点好奇

这种隐式本地化foreach 循环中发生。

所有这一切都在来自Private Variables via my() from perlsub的这个sn-p中得到了进一步的澄清

foreach 循环默认以local 的方式动态确定其索引变量的范围。但是,如果索引变量以关键字 my 为前缀,或者在作用域中已经存在该名称的词法,则会创建一个新的词法。

由于在这两种情况下都在内部创建了一个新的词法,因此没有任何实际区别。

我绝对支持并建议(始终)在那里使用my

【讨论】:

  • 明白了。我在这里看到的问题是$g 还没有在循环中。所以如果$g之前没有声明并赋值,那么$g实际上是一个空值。
  • @Gerry 在foreach my $i (1..4) { } 中,$i 的范围仅限于循环。它不存在“之前”。没有my 也是如此,如果$i 之前声明过——它一被看到就被本地化到循环的范围内。这就是上面的报价告诉我们的。
猜你喜欢
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多