2009-09-04 23 views
3

我不明白這裏發生了什麼:這些Perl使用行會發生什麼?

use PAR { file => 'foo.par', fallback => 1 }; 

我認爲這是一個匿名的哈希值。 use系列模塊如何使用它?你能說出一些光明嗎?

編輯:我對PAR模塊不感興趣。我只是對如何在幕後工作感興趣。我該如何配置我的模塊?

回答

7

更基本,這是有趣的hashref語法做什麼(使用perldoc -f use作爲參考):

說我們有這個基本模塊(把它放在Foo.pm在當前目錄):

package Foo; 

use Data::Dumper; 
sub import 
{ 
    print "import was passed these arguments: ". Dumper(\@_); 
} 

1; 
當我們撥打 perl -I. -wle'use Foo { a => 1, b => 2}'時,

,代碼Foo->import({a=>1, b=>2})被執行。因此,這是我們得到的輸出:

import was passed these arguments: $VAR1 = [ 
      'Foo', 
      { 
      'a' => 1, 
      'b' => 2 
      } 
     ]; 

基本上,這句法讓我們做的魔法與Exporter,但實際上你可以讓import()做任何你喜歡的(只是一定要記錄巨資,以不導致混淆!)

0

PAR是CPAN模塊Perl Archive Toolkit。 hashref是傳遞給PAR的配置參數。

代碼:

use PAR { file => 'foo.par, fallback => 1 }; 
use Foo::Bar; 

意味着使用Foo::Bar如果可用,否則退回到使用存檔「foo.par」(這大概持有Foo::Bar存檔版本)。

+0

哦。抱歉。我不明白是什麼讓語法起作用。我對PAR模塊本身並不感興趣,只是作者如何做到這一點。 – Geo 2009-09-04 21:25:31

+0

阿哈!在那種情況下,我剛剛提供了你的問題的真實答案。 :) – Ether 2009-09-04 21:43:59

7

當你模塊use,你可以傳遞一個參數列表給它。在你的例子中(似乎有一個錯字,缺少一個結尾引用),一個包含一個元素(一個散列引用)的列表被傳遞。

更一般地:

use Module LIST 

變爲這樣的:

BEGIN { 
    require Module; 
    Module->import(LIST); 
} 

BEGIN塊確保所有的事情發生在編譯時。 require將模塊加載到內存中,如果它尚未存在。然後在原始use語句中調用模塊的import()方法,並傳遞任何參數(如LIST)。

爲了讓您自己的模塊能夠處理這樣的參數,您的模塊需要定義一個import()方法。許多模塊不這樣做;相反,他們從Exporter類繼承import()。有關更多詳情,請參閱perldoc -f use

如果你的模塊定義了自己的import()方法,你要麼需要符號導出到客戶端代碼自己,或者更常見的是,使用由Exporter提供的export_to_level()方法。此方法的第一個參數是一個正整數,用於指定要將符號導出到的調用堆棧中的級別。最常見的值1意味着將一個級別的符號導出以上當前包 - 也就是說,使用您的模塊的客戶端代碼。這裏是你的import()方法需要做的概述。

sub import { 
    my ($class, @args) = @_; 

    # Do whatever you need to do with the LIST of arguments 
    # supplied by the client code using your module. 


    # Let Exporter do its normal work of exporting symbols 
    # into the client code using your module. 
    $class->export_to_level(1, @_); 
} 
2

是的,這是一個匿名散列。它作爲參數傳遞給模塊import方法。

0

直接回答你的問題:PAR確實this (line 340)

# called on "use PAR" 
sub import { 
    my $class = shift; 
    [...] 
    my @args = @_; 
    [...] 
    # process args to use PAR 'foo.par', { opts }, ...; 
    foreach my $par (@args) { 
     if (ref($par) eq 'HASH') { # <---- This is what handle's your case! 
      # we have been passed a hash reference 
      _import_hash_ref($par); 
     } 
     elsif ($par =~ /[?*{}\[\]]/) { 
      # implement globbing for PAR archives 
      [...] 
     } 
     else { 
      # ordinary string argument => file 
      [...] 
     } 
    } 

現在,不幸的是,一旦你深入到什麼是真正發生的事情,你就會意識到你選擇了最複雜的一個模塊上CPAN作爲一個學習的例子,所以我建議你看看fine documentation on modules instead。爲你提供一個指導,尋找什麼:當你「使用」一個模塊併爲use語句提供參數時,perl將加載模塊並用參數列表調用它的「import」方法。

在你的例子中,只有一個參數:對散列的引用。 {key =>「value」,key2 =>「value2」,...}語法是匿名哈希的構造函數。這些記錄在the perlref manual page中,但在the perlreftut tutorial中以更友好的術語解釋。