2009-01-11 75 views
20

我正在使用Perl測試框架。作爲測試的一部分,我可能需要爲任何給定的測試添加先決條件或後驗條件檢查,但不一定針對所有測試。我已經走到這一步,是這樣的:如何確定運行時是否存在Perl函數?

eval "&verify_precondition_TEST$n"; 
print [email protected] if [email protected]; 

不幸的是,這個輸出「未定義子程序& verify_precondition_TEST1所謂的......」如果功能不存在。

如何在嘗試調用之前提前確定函數是否存在?

回答

8

隨着定義:

if (eval "defined(&verify_precondition_TEST$n)") { 
    eval "&verify_precondition_TEST$n"; 
    print [email protected] if [email protected]; 
} 
else { 
    print "verify_precondition_TEST$n does not exist\n"; 
} 

編輯:嗯,我只想到的EVAL因爲它是在這個問題,但與帶來了萊昂TIMMERMANS符號引用,couldn」你做

if (defined(&{"verify_precondition_TEST$n"}) { 
    &{"verify_precondition_TEST$n"}; 
    print [email protected] if [email protected]; 
} 
else { 
    print "verify_precondition_TEST$n does not exist\n"; 
} 

即使有嚴格?

33
Package::Name->can('function') 

*Package::Name::function{CODE} 

# or no strict; *{ "Package::Name::$function" }{CODE} 

或只是生活與例外。如果您在eval中調用該函數並設置了$ @,則無法調用該函數。

最後,它聽起來像你可能想要Test :: Class而不是自己寫這個。

編輯:defined &function_name(或no strict; defined &{ $function_name }變體),如其他答案中所述,看起來是最好的方法。 UNIVERSAL :: can最適合你打算作爲方法調用的東西(風格),當Perl給你語法做你想做的事情時,爲什麼還要打亂符號表。

學習++ :)

+0

不幸的是,我在任何包外執行此操作,所以我得到:無法通過包「main」找到對象方法「can」。另外,我在一個完全沒有安裝Perl模塊的環境中使用古老版本的Perl(5.002)。 – 2009-01-11 22:18:39

+0

哇,5.002?我認爲出生之前出生:) – jrockway 2009-01-11 22:30:12

+0

是不是所有的緩衝區溢出問題的5.002? :) – 2009-01-12 18:55:45

15
sub function_exists {  
    no strict 'refs'; 
    my $funcname = shift; 
    return \&{$funcname} if defined &{$funcname}; 
    return; 
} 

if (my $subref = function_exists("verify_precondition_TEST$n") { 
    ... 
} 
4

我曾經使用Leon的方法,但是當我有多個包時,它失敗了。我不確定爲什麼;我認爲它涉及名稱空間之間的範圍傳播。這是我想出的解決方案。

my %symbols =(); 
my $package =__PACKAGE__; #bring it in at run-time 
{ 
    no strict; 
    %symbols = %{$package . "::"}; #See Symbol Tables on perlmod 
} 
print "$funcname not defined\n" if (! defined($symbols{$funcname}); 

參考文獻:perlmod的頁面上
__PACKAGE__參考。

Packages/__PACKAGE__關於Perl Training Australia的參考。

相關問題