我在子程序中传递和读取参数时遇到问题,该子程序应该有两个数组。
sub two_array_sum { # two_array_sum ( (1 2 3 4), (2, 4, 0, 1) ) -> (3, 6, 3, 5)
# I would like to use parameters @a and @b as simply as possible
}
# I would like to call two_array_sum here and pass two arrays, @c and @d
我已经在网上看过并尝试了几个例子,但没有一个适合我。
答案 0 :(得分:29)
有两种方法可以做到这一点:
但在我讨论这些之前 - 如果你在问题中显示的是关于你想做什么的程度 - 让我建议List::MoreUtils::pairwise
那么,你要写下这个:
my @sum = two_array_sum( @a, @b )
你只需写下:
my @sum = pairwise { $a + $b } @a, @b;
这就像push
一样。 (就像push
一样,它需要在某事上有@
sigil)
sub two_array_sub (\@\@) {
my ( $aref, $bref ) = @_;
...
}
当你这样做时
two_array_sub( @a, @b );
它有效。通常情况下,它只会在您的子组中显示为一个长列表。它们不适合所有人,正如您在下面的讨论中所看到的那样。
这就是每个人向你展示的方式。
some_sub( \@a, \@b );
他们很挑剔。如果您有refs:
,这将无效two_array_sub( $arr_ref, $brr_ref );
你必须像这样传递它们:
two_array_sub( @$arr_ref, @$brr_ref );
然而,因为使用深深嵌套的数组使“数组表达式”快速得到非常丑陋,我经常避免Perl的烦躁,因为你可以通过将它放在一个“字符”中来重载Perl将要采用的引用类型类“构造。 \[$@]
表示引用可以是标量或数组。
sub new_two_array_sub (\[$@]\[$@]) {
my $ref = shift;
my $arr = ref( $ref ) eq 'ARRAY' ? $ref : $$ref; # ref -> 'REF';
$ref = shift;
my $brr = ref( $ref ) eq 'ARRAY' ? $ref : $$ref;
...
}
所有这些都有效:
new_two_array_sub( @a, $self->{a_level}{an_array} );
new_two_array_sub( $arr, @b );
new_two_array_sub( @a, @b );
new_two_array_sub( $arr, $self->{a_level}{an_array} );
然而,由于某种原因,Perl对此仍然很挑剔:
new_two_array_sub( \@a, $b );
OR
new_two_array_sub( $a, [ 1..3 ] );
或者任何其他“构造函数”仍然可以被视为对数组的引用。幸运的是,您可以使用旧的 Perl 4 &
&new_two_array_sub( \@a, [ 1..3 ] );
然后子中的多路复用代码负责处理两个数组引用。
答案 1 :(得分:7)
将对数组的引用传递给函数:
two_array_sum( \@a, \@b )
并且不要使用a
或b
作为变量名称,因为$a
和$b
是特殊的(用于排序)。
答案 2 :(得分:6)
我会引用man perlref
,但你应该全部阅读:
Making References
References can be created in several ways.
1. By using the backslash operator on a variable, subroutine, or
value. (This works much like the & (address-of) operator in C.)
This typically creates another reference to a variable, because
there's already a reference to the variable in the symbol table.
But the symbol table reference might go away, and you'll still have
the reference that the backslash returned. Here are some examples:
$scalarref = \$foo;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&handler;
$globref = \*foo;
...
Using References
That's it for creating references. By now you're probably dying to
know how to use references to get back to your long-lost data. There
are several basic methods.
1. Anywhere you'd put an identifier (or chain of identifiers) as part
of a variable or subroutine name, you can replace the identifier
with a simple scalar variable containing a reference of the correct
type:
$bar = $$scalarref;
push(@$arrayref, $filename);
$$arrayref[0] = "January";
$$hashref{"KEY"} = "VALUE";
&$coderef(1,2,3);
print $globref "output\n";
答案 3 :(得分:4)
my @sums = two_array_sum(\@aArray, \@bArray);
sub two_array_sum { # two_array_sum ( (1 2 3 4), (2, 4, 0, 1) ) -> (3, 6, 3, 5)
my ($aRef, $bRef) = @_;
my @result = ();
my $idx = 0;
foreach my $aItem (@{$aRef}) {
my $bItem = $bRef->[$idx++];
push (@result, $aItem + $bItem);
}
return @result;
}
答案 4 :(得分:2)
您需要使用引用将数组或哈希值传递给子例程,例如:
sub two_array_sum {
my ($x, $y) = @_;
#process $x, $y;
}
two_array_sum(\@a, \@b);
答案 5 :(得分:2)
您无法将数组传递给函数。函数只能接受参数的标量列表。因此,您需要传递提供足够数据的标量来重新创建数组。
最简单的方法是将引用传递给数组。
sub two_array_sum {
my ($array0, $array1) = @_;
my @array0 = @$array0;
my @array1 = @$array1;
return map { $array0[$_] + $array1[$_] } 0..$#array0;
}
您甚至可以避免重建数组并直接使用引用。
sub two_array_sum {
my ($array0, $array1) = @_;
return map { $array0->[$_] + $array1->[$_] } 0..$#$array0;
}
用法:
my @array0 = (1, 2, 3, 4);
my @array1 = (2, 4, 0, 1);
two_array_sum(\@array0, \@array1);
方括号构造一个匿名数组(填充表达式的结果)并返回对该数组的引用。因此,上述内容也可以写成如下:
two_array_sum([1, 2, 3, 4], [2, 4, 0, 1]);
答案 6 :(得分:0)
这些方法都是规范的。另一种方法:
use strict;
my $data;
@{$data->{array1}} = qw(foo bar baz);
@{$data->{array2}} = qw(works for me);
testsub($data);
sub testsub
{
my ($data) = @_;
print join "\t", @{$data->{array1}}, "\n";
print join "\t", @{$data->{array2}}, "\n";
$data->{array1}[3] = "newitem";
delete $data->{array2};
push @{$data->{newarray}}, (1, 2, 3);
return $data;
}
当你这样做时,你可以对变量进行更严格的控制,而不是让老鼠的程序数据嵌入配置信息中。
一般来说,我在任何程序中都不会有超过三个或四个变量。
我还保留了一个系统 - 我使用列表哈希列表的哈希值。
$config->{server}[0]{prod}[0]{input}[0] = 'inputfile';
原因是只要我与每种方式交替一致,Data::Dumper
就可以转储整个结构 - 我可以更好地控制数据范围,并且可以轻松地传递整个结构。 / p>
我经常发现自己将这样的多个结构传递给子程序。作为标量,他们通过得很好,谢谢。