I'm refactoring a perl module in legacy code, and this is a function from the module:
sub get_user {
my $user = __PACKAGE__->{user};
if (!defined $user) {
# more code
__PACKAGE__->{user} = $user;
}
return $user;
}
This module compiles under use strict
. And there's no package variables defined.
What does __PACKAGE__->{user}
mean?
__PACKAGE__
is the name of the current package; your code is using it as a symbolic hash reference. So if your package is foo, it is setting $foo::foo{'user'}
. This is kind of a strange thing to do; I suspect it may be an error.
Because it's a symbolic reference, it shouldn't be allowed under strict. It seems to be, however, at least when the current package has multiple parts (e.g. Foo::Bar, not just Foo). I wouldn't depend on this bug staying in effect, though.
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
}
--output:--
10
X::Y
The package name may be 'X::Y' but the symbol table for the package is named 'X::Y::' (note the trailing colons). A symbol table is a perl hash, and the keys in the %X::Y:: hash are the global names used in the X::Y package. The corresponding values are the typeglobs for each name:
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
say $X::Y::{user}; #Hash name is %X::Y::
}
--output:--
10
X::Y
*X::Y::user
But the expression in the op:
__PACKAGE__->{user}
is equivalent to:
'X::Y'->{user}
I fail to see how that line will succeed in retrieving anything from a hash whose name is 'X::Y::' (ends in two colons). And in fact, I get this error:
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
say $X::Y::{user};
say __PACKAGE__->{user};
}
--output:--
10
X::Y
*X::Y::user
Use of uninitialized value in say at 2.pl line 13.
If the code actually creates a hash named %X::Y somewhere, then the code will run without errors:
use strict;
use warnings;
use 5.012;
%X::Y = (); #This hash has nothing to do with the hash named
#%X::Y::, which is the symbol table for the
#X::Y package.
$X::Y{user} = 'hello';
{
package X::Y;
sub get_user {
say __PACKAGE__->{user};
}
get_user;
}
--output:--
hello
As mentioned in the comment, the %X::Y hash has nothing to do with the X::Y package. In fact, the line:
%X::Y = ();
explicitly declares a variable called Y in the X package. The X package and the X::Y package are two different packages.
And there's no package variables defined
The sub name is a package variable:
use strict;
use warnings;
use 5.012;
{
package X::Y;
sub get_user {say 'hello';}
say $X::Y::{get_user};
}
--output:--
*X::Y::get_user
The fact that a typeglob for the name 'get_user' exists, means that the code uses at least one global variable named 'get_user'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With