2010-10-21 35 views
10

Làm cách nào tôi có thể chuyển hai mảng và chuỗi thành một phụ?Làm cách nào để chuyển hai mảng và chuỗi vào một chương trình con Perl?

Dưới đây là những gì tôi đang cố gắng để làm:

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"; 
} 

Output:

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. 

Trả lời

15

Bạn cần phải vượt qua từng mảng như một tài liệu tham khảo, nếu không @x của bạn trong phần phụ sẽ gobble phạm vi đối số TOÀN BỘ, để lại @y khoảng không quảng cáo trống và $z giá trị không xác định.

Điều này xảy ra bởi vì the comma operator - trong bối cảnh danh sách - sẽ biến một @x, @y, $z vào một mảng duy nhất bao gồm tất cả các yếu tố của @x Tiếp theo tất cả các yếu tố của @y và sau đó một giá trị của $z; của bạn @x trong phụ sẽ gobble lên phạm vi kết hợp ENTIRE của các đối số, để lại @y một mảng trống và $z một giá trị undef.

Một nguồn gây nhầm lẫn khác là việc bạn đặt tên cho cả hai biến là @x, mặc dù thực tế là chúng hoàn toàn độc lập với nhau do quy tắc phạm vi. Thực hành tốt là đặt tên cho chúng một cái gì đó khác biệt để tránh phải đoán bạn muốn sử dụng cái nào, ví dụ: gọi mảng đầu tiên của chương trình con @x2. Vui lòng lưu ý rằng bạn có thể chuyển mảng thành tham chiếu theo một trong hai cách - tham chiếu đến mảng ban đầu (phương pháp tiếp cận truyền theo tham chiếu thực) cũng như tham chiếu đến một bản sao của mảng - sẽ hoạt động như bạn muốn mã nguồn gốc của bạn cư xử và vượt qua giá trị.

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

Bạn cần phải vượt qua trong tài liệu tham khảo mảng:

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

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

bạn cần phải sử dụng tài liệu tham khảo:

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

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

bạn cũng có thể sử dụng nguyên mẫu chương trình con của Perl để loại bỏ các \ tại địa điểm cuộc gọi :

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

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

Nguyên mẫu (\@\@$) cho trình biên dịch biết rằng đối số cho Hello sẽ có ngữ cảnh tham chiếu mảng trên hai arg đầu tiên và ngữ cảnh vô hướng trên arg thứ ba. Nguyên mẫu không dành cho xác thực đối số, chúng cho phép bạn viết các chương trình con hoạt động giống như các nội trang dựng sẵn. Trong trường hợp này, như push.

Như DVK đề cập trong một nhận xét dưới đây, PBP khuyến nghị không nên sử dụng nguyên mẫu như quy tắc chung vì chúng có xu hướng được sử dụng không đúng để xác thực đối số. Tôi cảm thấy rằng việc sử dụng các tính năng nhất định của nguyên mẫu (\% hoặc \@ để áp đặt ngữ cảnh tham chiếu cho các loại số nhiều hoặc & làm arg đầu tiên cho phép map như cú pháp khối) biện minh vi phạm với PBP. Đặc biệt đúng là nếu sub đang được sử dụng để mở rộng cú pháp của Perl (các hàm trợ giúp, các hàm chỉ là cú pháp đường ...)

+0

vì lợi ích của tiết lộ đầy đủ, Perl Thực tiễn tốt nhất cuốn sách không khuyến khích sử dụng phụ mẫu (Tôi muốn lên bầu câu trả lời của bạn nếu nó được làm rõ thusly) - http://stackoverflow.com/questions/3991474/ is-using-prototype-to-declaration-array-reference-context-on-subroutine-args-a-good/3991558 # 3991558 – DVK

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"; 

} 
Các vấn đề liên quan