2009-01-08 76 views
4

我寧願這樣做:Perl是否存在andand?

say $shop->ShopperDueDate->andand->day_name(); 

與此:

say $shop->ShopperDueDate->day_name() if $shop->ShopperDueDate; 

任何想法?

(這個想法是由紅寶石andand擴展的啓發)

(實際上它是由Groovy語言啓發,但大多數人不知道;-)

更新:我認爲maybe()和eval {}都是很好的解決方案。這不是紅寶石,所以我不能期望從左到右閱讀所有的方法/函數,所以也許可以幫助。當然,eval的確是perl的方式。

+0

你也發佈到Perlmonks(http://www.perlmonks.org/index.pl?node_id=734774)。當您將相同的問題發佈到多個地方時,請讓人們知道,以便人們可以看到所有的答案,而不會浪費時間回答問題。 – 2009-01-08 07:19:32

回答

4

我想我已經寫過了。我剛剛上傳到CPAN,你可以找到它here

9

您可以使用Perl的eval語句來捕獲異常,包括那些從試圖調用上一個未定義的參數的方法:

eval { 
    say $shop->ShopperDueDate->day_name(); 
}; 

由於eval返回的最後一條語句進行評估,或undef失敗,你可以記錄天名稱,像這樣的變量:

my $day_name = eval { $shop->ShopperDueDate->day_name(); }; 

如果你真的要檢查外,你可以看看在特殊變量[email protected]。這通常是Perl內置異常的簡單字符串,但如果異常來自autodie或其他使用對象異常的代碼,則可能是完整的異常對象。

eval { 
    say $shop->ShopperDueDate->day_name(); 
}; 

if ([email protected]) { 
    say "The error was: [email protected]"; 
} 

它也可以串起來使用eval塊命令的序列。以下僅檢查是否是週末,前提是我們在查找$day_name時沒有發生任何異常情況。

eval { 
    my $day_name = $shop->ShopperDueDate->day_name(); 

    if ($day_name ~~ [ 'Saturday', 'Sunday' ]) { 
     say "I like weekends"; 
    } 
}; 

你能想到的eval爲同try從其他語言;的確,如果你使用CPAN的Error模塊,那麼你甚至可以拼寫它try。還值得注意的是,eval的塊形式(我已經在上面演示過了)不會帶來性能損失,並且會與代碼的其餘部分一起編譯。 eval(我沒有顯示)的字符串形式完全是一個不同的野獸,應該謹慎使用,如果有的話。

eval在技術上被認爲是Perl中的一個語句,因此是少數幾個可以在塊結尾處看到分號的地方之一。如果你不經常使用eval,很容易忘記這些。

保羅

9

我假設你的第二個例子最好是:

say $shop->ShopperDueDate ? $shop->ShopperDueDate->day_name() : undef; 

,而不是它實際上說。

無論如何,你不能該語法準確做沒有源過濾器,因爲undef不是對象,而是一個一元運算符,所以它不能有任何的方法。

相反,考慮一下:

package noop; 
our $maybe = bless [], 'noop'; 
sub AUTOLOAD { undef }; 

$noop::maybe是一個對象;儘管它的所有方法都返回undef。在其他地方,你就會有一個常規的功能是這樣的:

sub maybe { $_[0] || $noop::maybe; } 

然後,你可以這樣寫:

say maybe($shop->ShopperDueDate)->day_name() 

這工作,因爲「可能」的回報,如果真的返回它的參數,否則返回我們的$noop::maybe具有總是返回undef的方法的對象。

編輯:糾錯! ->andand->語法可能沒有源過濾器,通過使用XS與Perl的內部細節。 Leon Timmermans提供了一個採用此路線的實現。它全局替換undef()函數,所以它可能比我的方法慢很多。

+0

你爲什麼說會更好?這完全一樣的權利? – 2009-01-08 03:38:12

+0

閱讀它們的順序在他的例子中更有意義,恕我直言 – 2009-01-08 14:19:58

+0

Frew:第一個例子是say($ some_value),其中第二個例子大致相當於if($ some_value){say($ some_value)} - 前一個例子總是調用say(),而後者調用say()條件。 – geocar 2009-01-09 02:25:19

0

喜歡的東西(未測試):

use Object::Generic::False; 
sub UNIVERSAL::andand { $_[0] || Object::Generic::False->false } 

UNIVERSAL自動是所有其他類的子類,那麼這提供andand所有對象。 (顯然在UNIVERSAL中創建方法可能會在遠處產生衝突或令人驚訝的動作,因此不應該不小心使用它。)如果調用and和方法的對象爲true,則返回它; 否則返回一個通用的虛假對象,該對象返回其自身的任何方法調用。

相關問題