I was looking at this question, and while I was playing around, I came across this:
#! /usr/bin/env perl
#
# use warnings;
use strict;
use feature qw(say);
{
our $foo = "bar";
say "Foo = $foo";
}
say "Foo = $foo"; # This is line #12
Yes, I do have use warnings;
turned off...
When I run this, I get:
Variable "$foo" is not imported at ./test.pl line 12.
Global symbol "$foo" requires explicit package name at ./test.pl line 12.
Execution of ./test.pl aborted due to compilation errors.
Hmmm... I get the same "Variable "$foo" is not imported at ./test.pl line 12." error if I had done my $foo = "bar";
. I would understand this when I use my
because there is no variable $foo
once we leave the block. But, our
variables are suppose to be package scope. I could understand how $foo
might not have a value at that point, but this?
Also, what does the "Variable "$foo" is not imported at ./test.pl line 12." mean? I understand packages and importing, but there's only a single package here, main
. $foo
should be in the main
package. It doesn't need to be imported.
What is going on with my package variable that doesn't seem to be in the package after it falls out of scope?
So if you used
$::foo
, or created another alias withour $foo;
again, your program would work as expected. cmj
Let's try this...
#! /usr/bin/env perl
#
# use warnings;
use strict;
use feature qw(say);
{
our $foo = "bar";
say "Foo = $foo";
}
our $foo; # Redeclared
say "Foo = $foo"; # This is line #12
Now, this prints out:
bar
bar
As everyone who answered pointed out, our
merely makes an alias to the package variable of the same name, and it's lexically scoped. That means once the alias goes out of scope, so did my ability to access the value of $main::foo
with $foo
. That's something I never realized before.
However, as cjm pointed out, redeclaring our $foo;
restores the alias, and the already existing $main::foo
is aliased back to a new $foo
. When I redeclare our $foo;
, the value of $foo
is restored.
It's one of the things about our
variables that can be so confusing. You see a declaration our $foo;
, and suddenly not only does that variable exist, but it has a mysterious value. You have to search the program to see where that value could have come from.
Our declares a lexical alias to a package variable. This means that it's scoped just like my
. The difference is that it's backed by a package variable, so the variable doesn't go away when you exit the scope. Only the alias goes away.
So if you used $::foo
, or created another alias with our $foo
again, your program would work as expected.