Perl foreach循环变量范围

cha*_*mmu 4 perl foreach scope

在我编写下面的代码片段后,我是perl的新手并且与perl范围规则混淆:

#!/usr/bin/perl
my $i = 0;
foreach $i(5..10){
    print $i."\n";
}
print "Outside loop i = $i\n";
Run Code Online (Sandbox Code Playgroud)

我期望输出如下:

5
6
7
8
9
10
Outside loop i = 10
Run Code Online (Sandbox Code Playgroud)

但它的给予:

5
6
7
8
9
10
Outside loop i = 0
Run Code Online (Sandbox Code Playgroud)

因此,循环退出后变量$ i值不会改变.这是怎么回事?

Prg*_*ror 6

根据关于foreach循环的perldoc信息:这里

foreach循环遍历正常列表值,并依次将变量VAR设置为列表的每个元素.如果变量前面带有关键字my,则它是词法范围的,因此仅在循环中可见.否则,该变量隐含在循环的本地,并在退出循环时重新获得其前一个值.如果先前使用my声明了变量,它将使用该变量而不是全局变量,但它仍然本地化为循环.这种隐式定位仅在foreach循环中发生.

如果你想在循环外保留$ i的值,那么你可以在foreach循环调用中省略$ i并使用perl的特殊变量$ _,如下所示:

#!/usr/bin/perl

use strict;
use warnings;

my $i = 0;
foreach (5..10){
    print $_."\n";
    $i = $_;
}
print "Outside loop i = $i\n";
Run Code Online (Sandbox Code Playgroud)

5 6 7 8 9 10外环i = 10

  • 从明确命名的变量更改为"$ _"通常被认为是可维护性的倒退.使用"C style"`for`循环或`while`循环可能是解决这个问题的更好方法. (4认同)

Сух*_*й27 5

foreach将变量本地化到循环。

use strict;
use warnings;

my $adr;
my $i = 0;
foreach $i(5..10){
    $adr = \$i;
    print "$i ($adr)\n";
}
$adr = \$i;
print "Outside loop i = $i ($adr)\n";
Run Code Online (Sandbox Code Playgroud)

输出

5 (SCALAR(0x9d1e1d8))
6 (SCALAR(0x9d1e1d8))
7 (SCALAR(0x9d1e1d8))
8 (SCALAR(0x9d1e1d8))
9 (SCALAR(0x9d1e1d8))
10 (SCALAR(0x9d1e1d8))
Outside loop i = 0 (SCALAR(0x9d343a0))
Run Code Online (Sandbox Code Playgroud)

来自perldoc

foreach 循环迭代普通列表值,并依次将变量 VAR 设置为列表的每个元素。如果变量前面带有关键字 my,则它是词法作用域的,因此仅在循环内可见。否则,该变量对于循环来说是隐式本地的,并在退出循环时恢复其先前的值。如果该变量之前是用 my 声明的,则它使用该变量而不是全局变量,但它仍然本地化到循环。这种隐式本地化仅发生在 foreach 循环中。

$i为了保留你可以使用Clikefor循环的价值,

my $i = 0;
for ($i = 5; $i <= 10; $i++) { .. }
Run Code Online (Sandbox Code Playgroud)

虽然它的可读性不如 perlforeach

  • C 风格的循环可能可读性较差,但当您确实希望该值持续存在时,IMO 会更清晰。不过很容易犯相差一的错误:) (2认同)