当我输入以下代码并运行它时,它会输入< FONT COLOR ='foo'>< / FONT> 。但是,当我将my
添加到循环变量(for my $name (@colors)
)时,它会输入预期的< FONT COLOR ='red'>< / FONT> 。任何人都可以解释原因吗?
@colors = qw(red blue green yellow orange purple violet);
$name = 'foo';
for $name (@colors) {
no strict 'refs';
*$name = sub { "<FONT COLOR='$name'></FONT>" };
}
print red();
答案 0 :(得分:3)
在你的循环中你创建了几个潜艇。这些子可以看到它们在其中创建的上下文的所有变量。
如果我们使用局部/全局变量,则sub将始终看到最新值(变量插入字符串不会在编译时或“定义时间”发生,但是当执行sub时。 )在我们的例子中,循环的当前值 是foo
。
如果我们使用my
的词法变量,我们在循环中使用的变量在循环外部是不可见的,在循环的所有其他迭代中是不可见的。然而,它本身仍然可见。这称为闭包。闭包仅适用于词法变量,是实现信息隐藏或构建专门定制的子类的强大方法,如示例代码中所示。
答案 1 :(得分:2)
闭包捕获变量,而不是值。
将for my $x
视为每次循环创建一个新变量。内部子捕获此变量而不是类似命名的包变量,其值永远不会从foo
更改。
当你删除my
时,只创建了一个变量(一个包变量),所以在循环中创建的每个sub都会转换为同一个变量(其值从foo
变为{{1 } red
到... blue
到violet
)。
答案 2 :(得分:1)
for循环中使用的变量附加了一些魔法。对于循环的每次迭代,将其设置为适当的值。在循环结束后,$ name被设置为它的旧值。基本上,您创建的每个子组都会看到相同的变量,从而更改其值。我修改了你的例子来证明这一点:
@colors = qw(red blue green yellow orange purple violet);
$name = 'foo';
for $name (@colors) {
no strict 'refs';
*$name = sub { "<FONT COLOR='$name'></FONT>" };
print $name . &{$name} . "\n";
}
print red() . "\n";
您可以使用函数my
来定义局部变量,如下所示:
for my $name (@colors) {
根据经验,您应该始终在程序中use strict;
,这会强制执行变量的初始化。