2010-10-21 38 views
10

如何將兩個數組和一個字符串傳遞給子?如何將兩個數組和一個字符串傳遞給Perl子例程?

這裏就是我想要做的事:

use strict; 
use warnings; 

my @x = qw(AAAA BBBB CCCC DDDD EEEE); 
my @y = qw(1111 2222 3333 4444 5555); 

my $z = "hello"; 

Hello(@x,@y,$z); 

exit(0); 

sub Hello { 

    my (@x,@y,$z) = @_; 

    print "$_\n" for @x; 
    print "$_\n"; 
    print "$_\n" for @y; 
    print "$_\n"; 
    print "$z\n"; 
} 

輸出:

AAA 
BBBB 
CCCC 
DDDD 
EEEE 
1111 
2222 
3333 
4444 
5555 
hello 
Use of uninitialized value $_ in concatenation (.) or string at test.pl line 19. 

Use of uninitialized value $_ in concatenation (.) or string at test.pl line 21. 

Use of uninitialized value $z in concatenation (.) or string at test.pl line 22. 

回答

15

您需要將每一個陣列作爲參考的,否則你的@x在子將吞噬整個參數數組,剩下@y一個空陣列和$z undef值。

這是因爲the comma operator - 在列表環境 - 將變成一個@x, @y, $z成由隨後的@y所有的元素,然後$z的值的@x所有元素的單一陣列;您的子文件@x將吞噬整個參數的整個組合數組,使@y爲空數組,$z爲undef值。

另一個可能造成混淆的原因是您已命名變量@x,儘管它們由於作用域規則而彼此完全獨立。好的做法是將它們命名爲獨特的,以避免必須猜測你打算使用哪一個,例如,調用子程序的第一個數組@x2

請注意,您可以通過以下兩種方式之一傳遞數組作爲參考 - 對原始數組的引用(實際傳遞引用方法)以及引用數組的COPY - 這將表現就像你想要你的原始代碼行爲和傳遞價值一樣。

use strict; use warnings; 

my @x = qw(AAAA BBBB CCCC DDDD EEEE); 
my @y = qw(1111 2222 3333 4444 5555); 
my $z = "hello"; 

Hello(\@x,\@y,$z); 

# If you wish to pass a reference of a COPY of the array, 
# so that you can modify it inside the subroutine without modifying the original, 
# instead call Hello([@x], [@y], $z); 

exit(0); 

sub Hello { 

    my ($x2,$y2,$z2) = @_; 
    # Now, you de-reference array reference $x2 via @$x2 or $x2->[$i] 
    # where previously you used @x2 or $x2[$i] 
    print "$_\n" for @$x2; 
    print "$_\n"; 
    print "$_\n" for @$y2; 
    print "$_\n"; 
    print "$z2\n"; 

} 
3

你需要在數組引用傳遞:

sub Hello { 
    my ($x_ref, $y_ref, $z) = @_; 
    my @x = @$x_ref; 
    my @y = @$y_ref; 
    ... 
} 

Hello(\@x, \@y, $z); 
8

你需要使用引用:

sub Hello { 
    my ($x, $y, $z) = @_; 
    print "$_\n" for @$x; 
    ... 
} 

Hello(\@x, \@y, $z); 

,你也可以使用Perl的子程序原型,以消除\在調用點:

sub Hello (\@\@$) {...} 

Hello(@x, @y, $z); 

(\@\@$)原型告訴編譯器Hello的參數將在前兩個參數上有數組參考上下文,在第三個參數上有標量上下文。原型不適用於參數驗證,它們允許您編寫像內置函數一樣工作的子例程。在這種情況下,如push

由於DVK在下面的評論中提到,PBP建議不要將原型用作一般規則,因爲它們傾向於不適當地用於參數驗證。我覺得使用原型的某些特徵(\%\@爲多種類型強加參考上下文,或者將&作爲第一個參數允許map與塊語法一樣)證明了PBP的破壞。特別是如果sub被用來擴展Perl的語法(輔助函數,函數只是語法糖...)

+0

,使用子原型(如果它正是如此澄清我贊成票您的答案)Perl的最佳實踐的書不鼓勵 - http://stackoverflow.com/questions/3991474/ IS-使用的原型到申報陣列組基準上下文上子程序-ARGS-A-好/ 3991558#3991558 – DVK 2010-10-21 20:27:55

1
use strict; use warnings; 

my @x = qw(AAAA BBBB CCCC DDDD EEEE); my @y = qw(1111 2222 3333 4444 5555); 

my $z = "hello"; 

Hello(\@x,\@y,$z); 

exit(0); 

sub Hello { 
    my ($x,$y,$z) = @_; 

    print "$_\n" for @$x; 
    print "$_\n" for @$y; 
    print "$z\n"; 

} 
,在充分披露的利益
相關問題