如何将两个数组和一个字符串传递给子?
这是我正在尝试做的事情:
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";
}
Run Code Online (Sandbox Code Playgroud)
输出:
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.
Run Code Online (Sandbox Code Playgroud)
DVK*_*DVK 15
你需要传递每个数组作为参考,否则你@x
在sub中会吞噬整个参数数组,留下@y
一个空的arraay和$z
一个undef值.
发生这种情况是因为逗号运算符 - 在列表上下文中 - 将把a @x, @y, $z
变成一个单独的数组,该数组包含所有元素@x
后跟所有元素,@y
然后是值$z
; 你@x
在sub中将吞噬整个组合的参数数组,留下@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";
}
Run Code Online (Sandbox Code Playgroud)
你需要使用参考:
sub Hello {
my ($x, $y, $z) = @_;
print "$_\n" for @$x;
...
}
Hello(\@x, \@y, $z);
Run Code Online (Sandbox Code Playgroud)
您还可以使用Perl的子例程原型来消除\
呼叫站点:
sub Hello (\@\@$) {...}
Hello(@x, @y, $z);
Run Code Online (Sandbox Code Playgroud)
所述(\@\@$)
原型告诉用户参数给编译器Hello
将会对第三个参数上的前两个args数组参考上下文,并且标量上下文.原型不适用于参数验证,它们允许您编写与内置函数类似的子例程.在这种情况下,喜欢push
.
正如DVK在下面的评论中提到的那样,PBP建议不要使用原型作为一般规则,因为它们往往被不正确地用于参数验证.我觉得使用原型的某些特性(\%
或者\@
为多个类型强加引用上下文,或者&
作为允许map
类似块语法的第一个arg )证明使用PBP进行破解是正确的.特别正确的是,如果sub用于扩展Perl的语法(辅助函数,只是语法糖的函数......)