全局变量何时获得其值?

时间:2010-08-04 12:11:38

标签: perl

我遇到了一些奇怪的行为,暗示我不了解Perl脚本执行和初始化顺序的一些基本内容。以下示例:

#!/usr/bin/env perl

use strict;
use warnings;

print &get_keys(), "\n";

use vars qw/%hello/;  # same effect with 'my %hello = (...);'
%hello = ( a => 1, b => 2 );

sub get_keys
{
        return join(', ', sort keys %hello);
}

打印一个空字符串。意味着尽管变量已经可见,但由于尚未达到赋值的状态,因此它没有值。 (使用标量而不是散列会触发有关未初始化变量的警告。)

这是预期的行为吗?

我也很高兴RTFM指针。

3 个答案:

答案 0 :(得分:8)

来自perlsub

  

my同时具有编译时和   运行时效果。在编译时,   编译器会注意到它。该   这个的主要用处是   安静use strict 'vars' ....实际   初始化延迟到运行   但是,时间会被执行   适当的时间。

# At this point, %hello is a lexically scope variable (the my took effect
# at compile time), but it still has no keys.
print get_keys();

my %hello = ( a => 1, b => 2 );

# Now the hash has content.
print get_keys();

sub get_keys { join ' ', keys %hello, "\n" }

其他说明:(1)您应该使用myour而不是use vars。 (2)在正常情况下,不要使用前导符号调用函数:使用foo()而不是&foo()

答案 1 :(得分:4)

是的,这是预期的行为。您在分配到get_keys()之前致电%hello,因此%helloget_keys()为空。 (标量初始化为undef,而默认情况下数组和散列设置为空。)

如果您希望立即初始化%hello,请使用BEGIN块:

use vars qw/%hello/;
BEGIN {
    %hello = ( a => 1, b => 2 );
}

请注意,如果您使用的是my(或our,那么这不起作用:

BEGIN {
    my %hello = ( a => 1, b => 2 );
}

因为你必须在块之外声明变量,如下所示:

my %hello;
BEGIN {
    %hello = ( a => 1, b => 2 );
}

答案 2 :(得分:3)

use vars编译指示在编译时预先声明全局变量名。除非您为其指定任何值,否则该变量是未定义的。由于你在作业之前打印它,你理所当然地得到一个空字符串。

顺便说一下,这个实用主义已经过时了。来自perldoc vars

  

注意:对于当前包中的变量,提供的功能          通过这个pragma已被“我们的”声明取代,可用于          Perl v5.6.0或更高版本。请参阅perlfunc中的“our”。