I have working code, but I am trying to understand why it works. I am also trying to learn more about the internals of Perl 5 (perlbrew
, perl-5.26.1
, Cygwin x64
).
I know from perlvar
and strict
that use strict 'vars'
works by setting flags in $^H
. Perl then tests accesses to non-::
variables based on those flags. Somehow, both our
and use vars
mark variables so that they will pass the test. How do they do so?
For example:
perl -E 'package Foo;
use strict "vars";
use vars qw($foo);
say $foo;'
runs fine (although it produces no output). Based on the source for use vars
, I tried this, which I thought would have the same effect:
perl -E 'package Foo;
use strict "vars";
my $sym = "Foo::foo"; # <-- These two lines pulled straight
*$sym = \$$sym; # <-- from the source for the vars pragma
say $foo;'
However, it gave me an error: Global symbol "$foo" requires explicit package name
. I also tried $sym = "::Foo:foo"
in the above, with the same result.
I checked, and $Foo::foo
is in the symbol table:
$ perl -E 'package Foo;
use Data::Dumper;
use strict "vars";
my $sym = "Foo::foo";
*$sym = \$$sym;
say Dumper(\%{"Foo::"});' # <-- Foo's symbol table
Output:
$VAR1 = {
'BEGIN' => *Foo::BEGIN,
'Dumper' => *Foo::Dumper,
'foo' => *Foo::foo # <-- yep, it's there
};
What else is use vars
doing that I'm missing? Does our
do the same, or something different?
Update
Here's an A/B based on melpomene's answer:
Fails Succeeds
------------------------- ----------------------------------
package Foo; package Foo;
use strict "vars"; use strict "vars";
BEGIN {
package Bar;
my $sym="Foo::foo"; my $sym = "Foo::foo";
*$sym = \$$sym; *$sym = \$$sym;
}
say $foo; say $foo;
my
,state
andour
exempt from strict.use vars
creates a package variable in a different package and imports it, taking advantage of the fact that imported variables are exempt from strict. – Polak