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

Joe*_*nte 2 perl scoping lexical-scope

在这种情况下,为什么未初始化的变量的行为/交互方式与初始化变量不同:

use strict;
use warnings;

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

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

print "FOO: <$foo>\n";
print "BAR: <$bar>\n";
Run Code Online (Sandbox Code Playgroud)

结果是:

$ perl test.pl
FOO: <0>
BAR: <3>
Run Code Online (Sandbox Code Playgroud)

Perl版本:

$ perl -v

This is perl 5, version 22, subversion 0 (v5.22.0) built for x86_64-linux
Run Code Online (Sandbox Code Playgroud)

ike*_*ami 10

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

其次,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";
Run Code Online (Sandbox Code Playgroud)

更确切地说,

  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";

如你看到的,

  • 分配2$foo1.9.1,然后分配0$foo2.1.
  • 分配3$bar在1.12.1.