2010-07-30 50 views
6

我使用人兩種風格在Perl中傳遞命名參數,請參閱:參數傳遞的風格在Perl

use strict; 
use warnings; 
use Data::Dumper; 

sub foo { 
    print Dumper @_; 
} 

sub bar { 
    print Dumper @_; 
} 

foo(A => 'a', B => 'b'); 
bar({ A => 'a', B => 'b' }); 

什麼是使用FOO()風格,而不是巴()風格優勢?

回答

9

第二種方法將引用傳遞給哈希,而第一種方法只傳遞一個列表。

這裏有兩個方面:從理論上講,散列的引用在性能方面可能會更好,但對於短參數列表,這可以忽略不計。對於像foo(a => 1, b => 2)這樣的簡單調用,沒有性能差異,因爲@_實際上是原始值的別名。

但是,如果調用者已經具有散列中的值,則第一種樣式需要從散列轉換爲列表,然後再回到散列,這可能會很慢。

第二個方面是誰負責轉換爲散列的問題。第一種風格將其稱爲被調用的函數,如果這只是my %args = @_,它將產生奇怪的警告,如果參數列表不是偶數的長度。

這就是爲什麼我稍微偏好第二種風格(或者我使用Perl 6,它本身支持命名參數)。

+1

+1表示性能方面。 – 2010-07-30 13:09:23

+1

這些「性能方面」是不必要的微觀優化,不會產生實際好處。散列可以像清單一樣容易地使用:'foo(%hash)'或者hashref:'foo(%{$ hashref})'。堅持foo風格給用戶留下更多的權力。 – jmz 2010-07-30 13:42:47

+0

實際上,我自己的基準測試顯示(在多個安裝中)通過列表比引用更快 - 儘管* return *引用似乎更快。 – Axeman 2010-07-30 14:02:12

5

首先,這兩種方法的說明:

sub foo { 
    # Transform the array to a hash 
    my %args = @_; 

    foreach my $key (keys %args) { 
     print "$key => $args{$key}\n"; 
    } 
} 

# Pass an array of values 
foo(A=>'a', B=>'b'); 

在第一種情況下你正在做的是傳遞一個數組。在此上下文中的=>不是您可能認爲的散列鍵/值指示符。在這種情況下,它只是一個「胖逗號」。

sub bar { 
    my ($hash_ref) = @_; 
    foreach my $key (keys %$hash_ref) { 
     print "$key => $hash_ref->{$key}\n"; 
    } 
} 

# pass a ref to an anonymous hash 
bar({ A=>'a', B=>'b' }); 

在這第二種情況下,您將創建一個匿名散列並將該散列的引用作爲參數傳遞給該函數。

爲什麼選擇一個呢?在本書中,Perl最佳實踐第9章標題爲「命名參數」,作者建議在函數有三個以上參數時使用第二種樣式。他還喜歡它,因爲它在編譯時捕獲不匹配的參數數量,而不是在運行時。

+3

這是一段時間,因爲我讀了它,但我認爲建議使用3 +參數的hashref而不是一個標準的未命名參數列表,即調用'foo('a','b')',而不是在散列上推薦hashrefs – plusplus 2010-07-30 11:09:22

+3

@plusplus:該部分的標題是:「對於具有三個以上論題的任何子例程,使用命名參數的散列」。在這篇文章的主體中,他特別說過要使用哈希引用來替換轉換爲哈希的原始名稱/值對。 – 2010-07-30 13:06:28

+0

+1用於指定您的參考。 – 2010-07-30 16:03:42

6

foo(a => 1, b => 2)樣式是模擬命名參數的常用方法。 bar({a => 1, b => 2})通常只用於補充(可能是可選的)參數。

對於典型的用法,我更喜歡第一種形式。 {}是額外的打字,額外的噪音來讀取,並創建一個可能的錯誤,如果你遺漏了一個或兩個大括號。任何性能差異都可以忽略不計。 (如果不是這樣,你會遇到更大的問題。)另一方面,將參數包裝在匿名哈希構造函數中可以幫助您在編譯時而不是運行時找到錯誤。

第二種形式通常與位置參數混合使用。例如基準做到這一點:

cmpthese(10000, { 
    foo => \&foo, 
    bar => \&bar, 
}); 

雖然Tk的離開{}出來:

my $text = $w->Scrolled('Text', -width => 80, -height => 50); 

它通常是一個風格上的選擇。