我在遗留代码中重构了一个perl模块,这是模块中的一个函数:
sub get_user {
my $user = __PACKAGE__->{user};
if (!defined $user) {
# more code
__PACKAGE__->{user} = $user;
}
return $user;
}
Run Code Online (Sandbox Code Playgroud)
这个模块汇编下use strict.而且没有定义包变量.什么__PACKAGE__->{user}意思?
yst*_*sth 14
__PACKAGE__是当前包的名称; 您的代码将其用作符号哈希引用.所以如果你的包是foo,那就是设置$foo::foo{'user'}.这有点奇怪; 我怀疑这可能是一个错误.
因为它是一个象征性的参考,所以不应该在严格的范围内.然而,似乎至少当前的包有多个部分(例如Foo :: Bar,而不仅仅是Foo).不过,我不会依赖这个有效的bug.
use strict;
use warnings;
use 5.012;
{
package X::Y;
our $user = 10;
say $user;
say __PACKAGE__;
}
--output:--
10
X::Y
Run Code Online (Sandbox Code Playgroud)
包名称可以是'X :: Y',但包的符号表名为'X :: Y ::'(注意尾随冒号).符号表是perl哈希值,%X :: Y :: hash中的键是X :: Y包中使用的全局名称.相应的值是每个名称的typeglobs:
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
Run Code Online (Sandbox Code Playgroud)
但是op中的表达式:
__PACKAGE__->{user}
Run Code Online (Sandbox Code Playgroud)
相当于:
'X::Y'->{user}
Run Code Online (Sandbox Code Playgroud)
我没有看到该行如何成功地从名为'X :: Y ::'的哈希中检索任何内容(以两个冒号结尾).事实上,我得到这个错误:
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.
Run Code Online (Sandbox Code Playgroud)
如果代码实际上在某处创建了一个名为%X :: Y的哈希,那么代码将运行而不会出现错误:
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
Run Code Online (Sandbox Code Playgroud)
正如评论中所提到的,%X :: Y哈希与X :: Y包无关.事实上,该行:
%X::Y = ();
Run Code Online (Sandbox Code Playgroud)
在X包中显式声明一个名为Y的变量.X包和X :: Y包是两个不同的包.
而且没有定义包变量
子名是包变量:
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
Run Code Online (Sandbox Code Playgroud)
存在名为'get_user'的typeglob这一事实意味着代码至少使用一个名为'get_user'的全局变量.