2014-10-09 28 views
2

我在回顧Eric Strom先生的this question,尤其是response,並對其中更「神奇」的部分提出了疑問。請查看上下文鏈接的問題,因爲我只是想了解這個塊的內側部分:需要幫助理解腳本的部分(球體和參考文獻)

for (qw($SCALAR @ARRAY %HASH)) { 
    my ($sigil, $type) = /(.)(.+)/; 
    if (my $ref = *$glob{$type}) { 
     $vars{$sigil.$name} = /\$/ ? $$ref : $ref 
    } 
} 

因此,它遍歷三個字,打破各分爲兩個瓦爾,$sigil$typeif {}塊是我不瞭解的。我懷疑(..)內的部分獲得了$glob{$type}內的符號引用......必須有一些「魔術」(我還不瞭解的底層機制的某些深奧元素)依賴於那裏來確定類型的「指向」數據?

下一行也是部分令人困惑。在我看來,我們正在分配到變量哈希,但是什麼是rhs在做什麼?我們在最後一次操作中沒有分配到$_(分配了$ref),那麼與/\$/區塊中的比較是什麼?我的猜測是,如果我們正在處理一個標量(雖然我沒有看清楚我們是怎麼做的),但是我們去掉這個var並將其直接存儲在散列中,否則我們就存儲這個引用。

所以,只需要尋找這三行中發生的事情的一個小故事。非常感謝!

回答

4

迭代的元素是字符串。由於我們在循環的頂部沒有詞彙變量,因此元素變量爲$_。它在整個循環過程中保留了這個值。這些字符串中只有一個字符串具有字面美元符號,所以我們告訴'$SCALAR'和其他情況之間的差異。

所以它正在從包級別獲得3個槽位(有時候縮短了,而且的小小的含糊不清到「glob」)。 *g{SCALAR}*g{ARRAY}*g{HASH}。 glob存儲一個散列和一個數組作爲引用,所以我們只需將引用存儲到散列中。但是,glob將一個標量作爲引用標量存儲到標量中,因此需要取消引用,將其存儲爲標量。

所以,如果你有水珠*a,並在你的包你有:

our $a = 'boo'; 
our @a = (1, 2, 3); 
our %a = (One => 1, Two => 2); 

產生的散列要:

{ '$a' => 'boo' 
, '%a' => { One => 1, Two => 2 } 
, '@a' => [ 1, 2, 3 ] 
}; 

同時,水珠可以被認爲是這個樣子:

a => 
    { SCALAR => \'boo' 
    , ARRAY => [ 1, 2, 3 ] 
    , HASH => { One => 1, Two => 2 } 
    , CODE => undef 
    , IO  => undef 
    , GLOB => undef 
    }; 

所以要專門回答你的問題。

if (my $ref = *$glob{$type}) { 
    $vars{$sigil.$name} = /\$/ ? $$ref : $ref 
} 

如果沒有使用插槽,它是undef。因此$ref被指定爲參照或undef,其評估爲true作爲參考,並且false作爲undef。所以,如果我們有一個參考,那水珠槽的值存儲到哈希值,以存儲在哈希參考,如果它是一個「容器類型」,但走的是價值,如果它是一個標量。並且它與中的密鑰一起存儲在%vars哈希中。

+0

哦......我明白了。明確perl欺騙正在進行,但這是有點整潔!最後一點混淆......在原始鏈接答案中,變量'$ glob'存儲'* main :: eval_code'的值(例如,從測試腳本的輸出中複製;注意前導的'*') 。當'* $ glob {SCALAR}'被評估時,是評估(在僞代碼中)'*(* main :: eval_code){SCALAR}'? * *如何解決? – Jon 2014-10-09 16:53:25

+1

關於使用'$ a'來達到自己的目的通常的懲罰! – Borodin 2014-10-09 17:00:23

+0

@Jon,您知道簽名'''','@'和'%',也許您知道'&call_this_sub('a')'中的遺留CODE簽名',井符號有一個印記也是。最不爲人知的是'*',它告訴perl將其解決到系統表。 「符號」和typeglob幾乎是一回事。 – Axeman 2014-10-10 17:58:51

5

你在Perl語言的最晦澀的部分之一擊中,我可以從brian d foy的優秀掌握的Perl指你Symbol Tables and Typeglobs最好的解釋。還需要注意的是有在頁面的底部,其中最相關的是perldataTypeglobs and Filehandles Perl的自己的文檔中的相關章節進一步引用。

從本質上講,Perl的方式符號表的工作是每一個「藏匿」 - 「符號表散列」 - 他的名字是一樣的包,但有一對尾隨分號。所以默認包main的存儲稱爲%main::。如果你運行這個簡單的程序

perl -E"say for keys %main::" 

你會看到所有熟悉的內置標識符。

爲藏匿要素是類型團,這再次是散列,但具有對應於不同數據類型的密鑰,SCALARARRAYHASHCODE等,並且對於所述的參考值的參考具有該類型和標識符的數據項目。

假設你定義一個標量變量$xx,或更充分,$main:xx

our $xx = 99; 

現在藏匿main%main::,並與該標識符xx所有數據項的類型團被引用$main::{xx}所以,因爲typeglobs的印記是一個星標*,與標量標識符有一個美元$相同,我們可以將其解引用爲*{$main::{xx}}。要獲得引用具有標識xx變量,該類型團可以與SCALAR字符串進行索引,從而*{$main::{xx}}{SCALAR}。再次,這是一個參考到我們以後是變量,所以要收集它的價值了,需要再一次提領,如果你寫

say ${*{$main::{xx}}{SCALAR}}; 

然後你會看到99

寫在一個語句的時候,卻是相當stratighforward當分手這可能看起來有點複雜。在你的問題中的代碼具有可變$glob設置爲一個類型團的引用,如果我們say $ref我們得到SCALAR(0x1d12d94)或類似的對應於這相對於$main::xx

my $type = 'SCALAR'; 
my $glob = $main::{xx}; 
my $ref = *$glob{$type}; 

現在,這是$main::xx的引用作爲前,並且打印$$ref將按預期顯示99

後續分配給@vars是簡單的Perl,我不認爲你應該有任何理解,即一旦你得到包符號表是一堆typglobs,或者只是散列哈希的原則。

+0

And ...當我將'$ main :: {name}'分配給某個東西時,我得到了指向存儲條目(對於'name')的「指針」,這將是該符號的glob插槽。直到我輸出'$ main :: {name}'和'$ main :: name'時,我爲什麼要得到前導'''sigil'有點困惑。 – Jon 2014-10-09 18:20:28

+0

鮑羅丁,感謝您在perl的glob內部快速課程。你是對的,這是一門非常神祕的語言領域,但很明顯,有時候非常有用。我接受另一個人的回答作爲「問題的答案」,但不要將其解釋爲意味着我更重視你的回答!我用這兩個答案來獲得所需的理解。謝謝! – Jon 2014-10-10 16:07:34