2012-01-05 143 views
1

假設我們有一個子程序返回參考參考參數

sub aspirin { 
    my @items = qw(some items in here); 
    return \@items; 
} 

而另一子程序取一個數組引用

sub beetroot (\@) { 
    my $lst = shift; 
    print "$_\n" for @$lst; 
} 

我想從aspirin獲取數組和飼料beetroot與它。我想這樣做(的做法一個

my $L = aspirin; 
beetroot $L; 

但解釋抱怨,我需要做以下代替(方法):

my $L = aspirin; 
beetroot @$L; 

所以我的問題是:

  • 爲什麼不是方法A能正常工作?該參數實際上是一個Array引用,這是我們想要的;
  • 是否需要複製整個列表內容而不進行賦值的解引用(如方法B中的那個)? (我猜不是,因爲沒有明確的副本)。

謝謝您的回答

+0

這是「爲什麼99%的原因不需要原型的原因列表」中的第一項。 – 2012-01-05 13:43:42

回答

1

存在Perl原型來修改解析器的行爲,這很少需要。這也不例外。

如果「beetroot」沒有任何其他參數,那麼您應該使用@_而不是數組引用。

sub aspirin { 
    my @items = qw'some items in here'; 
    return @items if wantarray; # return a list in list context 
    return \@items; 
} 

sub beetroot { 
    print "$_\n" for @_; 
} 

my $L = aspirin; 
beetroot @$L; 

# the follow examples require the version of aspirin from this answer 

my @L = aspirin; 
beetroot @L; 

beetroot aspirin; # aspirin called in list context 

這將帶來額外的好處,即如果您只想輸入元素列表,則無需解析解析器。

這適用於新版本,但不適用於問題中的版本。

beetroot qw'some items in here'; 
beetroot aspirin; # aspirin called in list context 

爲了使它與問題中的問題一起工作,您必須創建一個匿名數組。有趣的是,這也適用於這個答案中的版本。

beetroot @{ [qw'some items in here'] }; 
# the follow examples use the version of aspirin from this answer 
beetroot @{ [aspirin] }; 
beetroot @{ scalar aspirin }; 
beetroot @{ aspirin }; 

如果你真的想 「beetroot」 與數組引用工作。 我會這樣寫。

sub beetroot{ 
    my($lst) = @_; # similar to my $lst = shift 
    print "$_\n" for @$lst; 
} 

my $L = aspirin; 
beetroot $L; 

my @L = aspirin; # using the aspirin from this answer 
beetroot \@L; 

beetroot [qw'some items in here']; 
# the follow examples use the version of aspirin from this answer 
beetroot scalar aspirin; # force aspirin to return an array reference 
beetroot [ aspirin ]; # copy the array 

這樣,如果你想使用引用減少的Perl的內存佔用,或者你有其他投入「beetroot」我只會寫。

6

原型\@並不意味着數組引用。這意味着給我一個數組,但我會得到它的一個引用作爲參數(見perldoc perlsub

報價:

任何反斜槓的原型人物代表實際的論點,即 絕對必須以該字符開始如部分的@_ 將是在 子程序調用中給出的實際參數的引用傳遞的值,通過施加到"\"該參數獲得。

或換句話說,不要使用原型,除非你真的知道他們在做什麼。

+0

關於'perldoc perlsub'我可以這樣理解:「這個特性的目的主要是讓你定義像內置函數一樣工作的子程序。正如我所能理解的(糾正我,如果我錯了),內置函數與普通函數不同,它們可能有副作用,所以我應該只在我的數組上使用'\ @'時才使用'\ @'參數。它是否正確? – Dacav 2012-01-05 13:25:03

+0

不正確;正常功能也可能有副作用。相反,請考慮如何重新執行調用'push @ a,@ b'。如果你調用'my_push @ a,@ b',你的函數將會收到一個名爲'@ _'的數組,無法知道'@ a'結束和'@ b'開始的位置。要解決這個問題,你可以使用引用('my_push \ @a,\ @ b'或'my_push \ @ a,@ b')調用sub。或者用一個原型('sub my_push(\ @@){...}'),告訴Perl期望一個數組(不是列表!)作爲函數的第一個參數,並將它作爲函數傳遞給你的子例程一個數組引用,讓你說'my_push @ a,@ b'並讓Perl做你的意思。 – mob 2012-01-05 16:42:04