2009-11-18 17 views
3

如果我通過散列子:

parse(\%data); 

我應該使用$_[0]變量第一或者是好的,保持訪問$_[0]每當我想從哈希的元素?澄清:

sub parse 
{ $var1 = $_[0]->{'elem1'}; 
    $var2 = $_[0]->{'elem2'}; 
    $var3 = $_[0]->{'elem3'}; 
    $var4 = $_[0]->{'elem4'}; 
    $var5 = $_[0]->{'elem5'}; 
} 
# Versus 
sub parse 
{ my $hr = $_[0]; 
    $var1 = $hr->{'elem1'}; 
    $var2 = $hr->{'elem2'}; 
    $var3 = $hr->{'elem3'}; 
    $var4 = $hr->{'elem4'}; 
    $var5 = $hr->{'elem5'}; 
} 

是第二個版本更正確的,因爲它沒有繼續訪問參數數組,還是Perl的最終interpereting無論如何他們以同樣的方式?

回答

11

在這種情況下,沒有區別,因爲您傳遞的是散列引用。但如果通過標量將有差異:

sub rtrim { 
    ## remove tailing spaces from first argument 
    $_[0] =~ s/\s+$//; 
} 
rtrim($str); ## value of the variable will be changed 

sub rtrim_bugged { 
    my $str = $_[0]; ## this makes a copy of variable 
    $str =~ s/\s+$//; 
} 
rtrim($str); ## value of the variable will stay the same 

如果您傳遞哈希引用,則只創建引用的副本。但哈希本身將是相同的。所以如果你關心代碼可讀性那麼我建議你爲你的所有參數創建一個變量。例如:

sub parse { 
    ## you can easily add new parameters to this function 
    my ($hr) = @_; 

    my $var1 = $hr->{'elem1'}; 
    my $var2 = $hr->{'elem2'}; 
    my $var3 = $hr->{'elem3'}; 
    my $var4 = $hr->{'elem4'}; 
    my $var5 = $hr->{'elem5'}; 
} 

此外,更多描述性變量名稱也會改善您的代碼。

0

由於他們的工作,都是精細,通常的做法是shift關閉參數。

sub parse { my $hr = shift; my $var1 = $hr->{'elem1'}; } 
+3

我不會說「這是常見的做法。」這實際上是一場純Perl的聖戰。 – 2009-11-18 18:07:58

+1

my($ one,$ two)=((shift),(shift));或者我的($ 1,$ 2)= @_; ? – user105033 2009-11-18 18:16:04

+4

'$ hr - > {elem1}'或$ $$ hr {elem1}'很帥氣。 $$ hr - > {elem1}'不起作用。 – friedo 2009-11-18 19:30:52

5

您是微型優化;儘量避免這種情況。去任何最可讀/可維護的。通常這是你使用詞法變量的地方,因爲它的名字表明它的目的...但是如果你使用的名字如$data$x這顯然不適用。

就技術細節而言,對於大多數目的,您可以通過計算perl將使用的基本操作的數量來估計所花費的時間。對於你的$_[0],非詞彙數組變量中的元素查找需要多個操作:一個獲取glob,一個獲取glob的數組部分,一個或多個獲取索引(只有一個用於常量),以及一個查找元素。另一方面是$hr是單個操作。爲了迎合@_的直接用戶,有一種優化可以將$_[0]的操作減少爲單個組合操作(當索引介於0和255之間時),但在您的情況下不會使用它,因爲hash-deref上下文數組元素查找需要額外的標誌(以支持自動生成),並且該優化操作不支持該標誌。

總之,使用詞彙將會更加可讀,並且(如果您多次使用它)不知不覺會更快。

7

對於shift效率VS直接訪問@_的一般討論,請參見:

至於你具體的代碼,我會用shift,但用散列片簡化數據提取:

sub parse 
{ 
    my $hr = shift; 
    my ($var1, $var2, $var3, $var4, $var5) = @{$hr}{qw(elem1 elem2 elem3 elem4 elem5)}; 
} 

我會假設這個方法對這些變量做了一些其他的操作,這使得將它們保存在不同的變量中是值得的(也許哈希是隻讀的,並且在插入其他數據之前需要進行一些修改? ) - 否則爲什麼不把它們留在他們開始的hashref?

+5

散列片+1,世界遺忘的奇蹟。 – 2009-11-18 19:36:16

+0

將項目放入變量中的一個很好的理由是提供了'strict'vars''提供的錯字保護。你也可以通過'Hash :: Util :: lock_keys'來鎖定你的哈希鍵。 – daotoad 2009-11-18 20:09:15

+0

我的功能完全不是我所做的,我只是舉了一個例子。 – user105033 2009-11-18 21:07:43

4

我的規則是我儘量不要在比兩個語句更長的子例程中使用$_[0]。之後,所有東西都得到一個用戶定義的變量。

你爲什麼要把所有的散列值複製到變量中?只要將它們留在它們所屬的散列中即可。這比你想的要好得多。

+1

我只在兩種情況下使用'$ _ [0]':類訪問器(符合你的「幾條語句」規則)以及罕見的情況下,我想修改參數並需要保留別名。 – 2009-11-18 20:49:41

+0

@Michael Carman:如果你願意,你可以避免使用'$ _ [0]'並且明確地記錄你的就地修改,像這樣:'perl -Mstrict -wle'sub arg_aliases {\ @_} sub foo {my $ arg_aliases =&arg_aliases;我($ foo)= @_;打印「foo是$ foo」; $ arg_aliases - > [0] =「plugh」} my $ foo =「xyzzy」; FOO($ foo的);打印「foo現在是$ foo」'' – ysth 2009-11-19 01:38:41

+0

但生病了 – ysth 2009-11-19 01:39:39

相關問題