2012-06-21 32 views
4

模塊:./FOO/BAR/Foobar.pm的Perl:麻煩與出口商

use strict; 
use warnings; 

package Foobar; 
    our($VERSION , @ISA , @EXPORT , @EXPORT_OK , %EXPORT_TAGS , $FOO); 
    BEGIN { 
     require Exporter; 
     @ISA  = qw(Exporter); 
     @EXPORT_OK = qw(&foo); 
    } 

    sub foo { 
     print "Loaded\n"; 
     $FOO = q{some val}; 
    } 

1; 

計劃:./Caller.pl

#!/usr/bin/perl 

    use strict; 
    use warnings; 

    use FOO::BAR::Foobar qw/foo/; 

    Foobar::foo(); # works 
    foo();   # errors out - can't find &main::foo 

我會列出所有我試過的東西,但有一個很多 - 正如你所看到的,我有更多的全球Foobar全球比列出。我已經刪除了BEGIN,並按照PerlMonks上的[舊]帖子中的建議完成了其他一些事情。

我想我曾經在某處讀過,如果軟件包名稱與模塊名稱相同,Exporter默認以某種方式工作。我不知道是否將模塊放在子目錄中可能會改變該行爲(?)。不過,我很想看看我是如何搞砸的。

回答

5

如果模塊位於FOO/BAR/Foobar.pm中,那麼包名應該是FOO::BAR::Foobar

我還會刪除@EXPORT_OK數組中的&符號。

+0

+1 ---似乎我懷疑有一些優點。有沒有其他重命名包的方法? – vol7ron

+0

我回答了我上面的問題(在評論中)。我會接受這個答案 - 儘管如此,我仍然希望找到一些關於導入不同包的變量/函數的資源 – vol7ron

4

除了choroba的答案,我發現這個postSherm Pendley,我認爲這是同一個職位,我讀幾年前:

在該出口功能的非面向對象的模塊,它們必須是相同的爲 出口商做它的事情。當您使用()的模塊 - 姑且稱之爲「富」, 以下步驟基本上是發生了什麼:

BEGIN { 
    require Foo; 
    import Foo qw(args); 
} 

第二步是可選的 - 如果有模塊 美孚沒有進口()函數中, use()仍然會成功。

現在,讓我們假設包Bar在Foo.pm中。 Foo.pm由 編譯,require()沒有問題。因爲它的代碼位於包Bar中,所以顯式聲明或從Exporter繼承的import()函數 也編譯到該包中。

但是use()仍嘗試調用程序包 Foo中的import()函數。更糟糕的是,因爲import()是可選的,所以默默地失敗。 只有用戶纔會知道出了什麼問題,因爲在Bar中聲明的函數沒有一個指定的包名稱,即Bar :: baz(),因此沒有完整的 ,因爲import()未能在當前包中爲他們創建別名 。

其他的東西也可以依賴於文件名=軟件包約定。例如,以 perldoc爲例。如果您的模塊的用戶運行「perldoc Foo」獲取您的模塊的文檔 ,它將讀取Foo.pm中的文檔。如果這些文檔描述名爲「Bar」的軟件包,用戶的 將會混淆。「

即使你的模塊‘純’OO並沒有出口任何東西,下面 既定的慣例,有助於避免混亂 - 想象維護 程序員看你的腳本,一年後的今天,看到這一點:

use Foo; 
my $bar = Bar->new(); 

這不是很直觀的看到Foo.pm.

定義的類酒吧

所以,不,它不是在理論上必需的。但它們命名 相同的慣例沿襲廣泛,在實踐中它真的更多或需要10個以下。


所以,看來如果你有每個模塊的多個軟件包中,只有共享相同的名稱的文件可以導出其變量/功能之一。我懷疑如果你要爲其他軟件包(?)創建自己的導入功能,可以讓它工作。

總之,在我的例子,如果我不想叫整個層次樹,我可以設置的lib:

use lib './FOO/BAR'; 
use Foobar qw/foo/; # instead of "use FOO::BAR::Foobar" 

這將意味着我仍然有Foobar.pm和內它package Foobar而不是package FOO::BAR::Foobar

+0

這是一個很好的閱讀。謝謝。 – simbabque