When does a global variable get its value assigned?
I encountered some strange behavior which hints that I do not understand some basic things about Perl script 开发者_运维技巧execution and initialization order. The following example:
#!/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);
}
prints an empty string. Meaning that though variable is already visible, since the state with assignment wasn't yet reached, it has no value. (Using a scalar instead of the hash would trigger a warning about uninitialized variable.)
Is that intended behavior?
I would be also glad for the RTFM pointers.
From perlsub:
A
my
has both a compile-time and a run-time effect. At compile time, the compiler takes notice of it. The principal usefulness of this is to quietuse strict 'vars'
.... Actual initialization is delayed until run time, though, so it gets executed at the appropriate time.
# 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" }
Other notes: (1) You should be using my
or our
rather than use vars
. (2) Under normal circumstances, don't call functions with a leading ampersand: use foo()
rather than &foo()
.
Yes, it's intended behaviour. You call get_keys()
before you assign to %hello
, so %hello
is empty in get_keys()
. (Scalars are initialised to undef
, while arrays and hashes are set to be empty by default.)
If you want %hello
to be initialised immediately, use a BEGIN block:
use vars qw/%hello/;
BEGIN {
%hello = ( a => 1, b => 2 );
}
Note that if you were using my
(or our
, for that matter) then this wouldn't work:
BEGIN {
my %hello = ( a => 1, b => 2 );
}
because you have to declare the variable outside the block, like so:
my %hello;
BEGIN {
%hello = ( a => 1, b => 2 );
}
The use vars
pragma predeclares global variable name at compile time. The variable is undefined unless you assign any value to it. Since you print it before the assignment, you rightfully get an empty string.
BTW, this pragma is obsolete. From perldoc vars:
NOTE: For variables in the current package, the functionality provided by this pragma has been superseded by "our" declarations, available in Perl v5.6.0 or later. See "our" in perlfunc.
精彩评论