如何将两个数组和一个字符串传递给子?
这是我正在尝试做的事情:
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.
答案 0 :(得分:15)
您需要将每个数组作为参考传递,否则子中的@x
将吞噬ENTIRE参数数组,使@y
成为空的arraay并$z
undef值。
这是因为the comma operator - 在列表上下文中 - 会将@x, @y, $z
转换为由@x
的所有元素组成的单个数组,后跟@y
的所有元素然后是$z
的值;子中的@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";
}
答案 1 :(得分:8)
你需要使用引用:
sub Hello {
my ($x, $y, $z) = @_;
print "$_\n" for @$x;
...
}
Hello(\@x, \@y, $z);
你也可以使用Perl的子程序原型消除呼叫站点的\
:
sub Hello (\@\@$) {...}
Hello(@x, @y, $z);
(\@\@$)
原型告诉编译器Hello
的参数将在前两个args上具有数组引用上下文,在第三个arg上具有标量上下文。原型不适用于参数验证,它们允许您编写与内置函数类似的子例程。在这种情况下,例如push
。
正如DVK在下面的评论中提到的那样,PBP建议不要使用原型作为一般规则,因为它们往往被不正确地用于参数验证。我觉得使用原型的某些功能(\%
或\@
来强加多个类型的引用上下文,或者&
作为第一个arg来允许map
像块语法一样对齐打破PBP。特别正确的是,如果使用sub来扩展Perl的语法(辅助函数,只是语法糖的函数......)
答案 2 :(得分:3)
您需要传入数组引用:
sub Hello {
my ( $x_ref, $y_ref, $z ) = @_;
my @x = @$x_ref;
my @y = @$y_ref;
...
}
Hello( \@x, \@y, $z );
答案 3 :(得分: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";
}