使用 our 和 BEGIN 块交互声明的变量

Variables declared with our and BEGIN block interactions

在这种情况下,为什么未初始化的变量 behave/interact 与已初始化的变量不同:

use strict;
use warnings;

our($foo) = 0;
BEGIN {
        $foo = 2;
}

our($bar);
BEGIN {
        $bar = 3;
}

print "FOO: <$foo>\n";
print "BAR: <$bar>\n";

结果:

$ perl test.pl
FOO: <0>
BAR: <3>

Perl 版本:

$ perl -v

This is perl 5, version 22, subversion 0 (v5.22.0) built for x86_64-linux

首先,它不是初始化器;这是一个普通的旧任务。它发生在执行代码时,而不是创建变量时。

其次,BEGIN 个块在块被编译后立即被评估。

因此,你写的基本上等同于:

# Compile phase
use strict;
use warnings;    
our $foo;
$foo = 2;
our $bar;
$bar = 3;

# Runtime phase
($foo) = 0;
($bar);
print "FOO: <$foo>\n";
print "BAR: <$bar>\n";

更准确地说,

  1. 编译阶段
    1. 编译use strict;.
    2. 执行require strict;.
    3. 执行import strict;.
    4. 编译use warnings;.
    5. 执行require warnings;.
    6. 执行import warnings;.
    7. 编译our($foo) = 0;。 (仅创建 $foo。)
    8. 编译BEGIN块:
      1. 编译$foo = 2;.
    9. 执行BEGIN块:
      1. 执行$foo = 2;.
    10. 编译our($bar);。 (仅创建 $bar。)
    11. 编译BEGIN块:
      1. 编译$bar = 3;.
    12. 执行BEGIN块:
      1. 执行$bar = 3;.
    13. 编译print "FOO: <$foo>\n";.
    14. 编译print "BAR: <$bar>\n";.
  2. 运行时阶段
    1. 执行($foo) = 0;.
    2. 执行($bar);.
    3. 执行print "FOO: <$foo>\n";
    4. 执行print "BAR: <$bar>\n";

如您所见,

  • 您在 1.9.1 中将 2 分配给 $foo,然后在 2.1 中将 0 分配给 $foo
  • 您在 1.12.1 中将 3 分配给 $bar