2010-07-07 155 views
19

我重構遺留代碼Perl模塊,這是從該模塊的功能:__PACKAGE __-> {foo}是什麼意思?

sub get_user { 
    my $user = __PACKAGE__->{user}; 
    if (!defined $user) { 
     # more code 
     __PACKAGE__->{user} = $user; 
    } 
    return $user; 
} 

該模塊use strict下編譯。並沒有定義包變量。 __PACKAGE__->{user}是什麼意思?

回答

14

__PACKAGE__是當前包的名稱;您的代碼將其用作符號散列引用。所以如果你的軟件包是foo,那麼設置爲$foo::foo{'user'}。這是一件很奇怪的事情;我懷疑這可能是一個錯誤。

因爲它是一個符號引用,它不應該被嚴格禁止。但是,至少當前包中包含多個部分(例如Foo :: Bar,而不僅僅是Foo)似乎是這樣。 雖然,我不會依賴這個bug繼續生效。

+1

我的猜測是,* eugene y *的例子中的__PACKAGE__是一個「Compound :: Namespace :: Construction」而不是'SimpleOne'(沒有冒號),它似乎在5.10下繞過了我的狹窄。 – pilcrow 2010-07-07 15:12:44

+3

......當然!因爲'__PACKAGE __-> {key}'在一個簡單的命名空間中是例如'main-> {key}'(錯誤:'全局符號「%main」需要明確的包名'),但是在一個複合命名空間中是例如。,'My :: Pkg - > {key}',這是對'My'包下的哈希'%Pkg'的完全限定引用。我會期待一個「空白字」的錯誤,但'__PACKAGE__的特殊處理必須迴避。 – pilcrow 2010-07-07 15:22:57

+2

啊。這對我來說似乎是一個錯誤。 – ysth 2010-07-07 16:20:36

-5

__PACKAGE__是一個散列。該語法訪問鍵控值。

7
use strict; 
use warnings; 
use 5.012; 

{ 
    package X::Y; 

    our $user = 10; 
    say $user; 

    say __PACKAGE__; 

} 


--output:-- 
10 
X::Y 

包名可能是'X :: Y',但包的符號表被命名爲'X :: Y ::'(注意尾部冒號)。符號表是perl散列,並且%X :: Y :: hash中的鍵是X :: Y包中使用的全局名稱。對應的值是每個名稱的類型團:

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 

但在運算表達式:

__PACKAGE__->{user} 

等同於:

'X::Y'->{user} 

我看不出那怎麼行會成功地從名爲'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. 

如果代碼實際上創建了一個名爲哈希%X ::Ÿ某處,那麼代碼將沒有錯誤運行:

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 

正如提到的評論,%X :: Y哈希與X :: Y包無關。實際上,該行:

%X::Y =(); 

顯式聲明X包中的一個名爲Y的變量。 X包和X :: Y包是兩個不同的包。

And there's no package variables defined

子名字是一個包變量:

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 

的事實,即名稱爲「GET_USER」存在,一個類型團意味着代碼使用名爲「GET_USER」中至少一個全局變量。