__PACKAGE __-> {foo}是什么意思?

Eug*_*ash 19 perl

我在遗留代码中重构了一个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.

  • ... 当然!因为简单命名空间中的`__PACKAGE __-> {key}`是例如`main - > {key}`(错误:`全局符号"%main"需要显式包名称`),但在复合命名空间中,例如,`My :: Pkg - > {key}`,它是对`My`包下的哈希`%Pkg`的完全限定引用.我希望有一个"赤字"错误,但是`__PACKAGE__的特殊处理必须回避这一点. (3认同)
  • 啊.这对我来说似乎是个错误. (2认同)

7st*_*tud 7

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'的全局变量.