coderefs 中的变量范围如果是 perl,需要对奇怪行为的解释

Variable scopes in coderefs if perl, need an explanation of strange behavior

为什么@coderefs 中的coderefs 返回的$copy_of_i 的值相同?

use Modern::Perl;
my @coderefs = ();
for (my $i = 0; $i < 5; $i++){
    push @coderefs, sub { 
        my $copy_of_i = $i;
        return $copy_of_i;
    };
}

say $coderefs[1]->();
say $coderefs[3]->();

我认为 $copy_of_i 对于添加到 @coderefs 的每个代码引用都是本地的,因此包含在循环的给定迭代中分配给 $copy_of_i 的 $i 的当前值。但是,如果我们用 'say' 显示几个 $copi_of_i 的值,我们将看到它们具有相同的值,就好像 $copy_of_i 不是每个新的本地值一样创建代码参考。为什么?

您希望具有与闭包关联的不同值,但您只有一个变量 $i 用于捕获所有闭包。您需要为每个要捕获的闭包创建一个变量,因此 $copy_of_i 应该在闭包之外创建。在调用闭包时创建副本为时已晚; $i 此时不再包含所需的值。

for (my $i = 0; $i < 5; $i++){
    my $copy_of_i = $i;
    push @coderefs, sub { 
      return $copy_of_i;
    };
}

顺便说一下,for my $i (0 .. 5) 优于 for (my $i = 0; $i < 5; $i++),它的优点是为循环的每次迭代创建一个新变量,因此您可以简单地使用

my @coderefs;
for my $i (0 .. 4) {
    push @coderefs, sub { 
      return $i;
    };
}