在perl中所有sub的参数写入@_数组,如下所示:
call_any_sub($a,$b,$c);
sub call_any_sub {
my $s_a = shift;
my $s_b = shift;
my $s_c = shift;
}
但是,如果我想将数组作为参数传递给sub,我应该使用:
call_any_sub(@data_array);
sub call_any_sub {
my @data = @_;
}
而不是类似的:
call_any_sub(@data_array);
sub call_any_sub {
my @data = shift;
}
那么,为什么@data_array会替换参数数组而不是写入(如预期的那样)?
答案 0 :(得分:6)
只能将一个标量列表传递给子程序(这就是他们可以返回的全部内容)。毕竟,参数作为数组(@_
)呈现给sub,而数组只能包含标量。
您可以(低效率)在子
中重新创建数组 sub foo {
my @bars = @_;
say for @bars;
}
foo(@bars);
或者您可以传递对数组的引用
sub foo {
my ($bars) = @_;
say for @$bars;
}
foo(\@bars);
答案 1 :(得分:2)
您需要了解shift的作用。
shift
/ unshift
对命令与pop
/ push
命令对并行。所有这些命令都在数组上运行。默认情况下,shift
(仅shift
)在子例程中调用@_
数组,在主程序中调用@ARGV
时。这意味着以下两个语句在子例程中是相同的:
my $foo = shift @_; # Explicit Argument
my $foo = shift # Implicit Argument
Perl的参数传递是一个有趣的概念,因为它几乎没有像几乎所有其他程序那样进行命名参数传递。相反,所有内容都作为一长串标量传递。当你没有传入标量时,这很难。
如果我只传入一个哈希或数组,它可以正常工作:
munge_hash ( %foo );
sub munge_hash {
my %hash = @_;
...
}
而且,如果你传入多个参数和一个数组,你必须要小心。在这种情况下,数组必须是参数列表中的最后一个:
my $foo = "floop";
my $bar = "bloop";
my @array = qw(loop coop soop);
munge_this ( $foo, $bar, @array );
sub munge_this {
say join ":", @_; # Prints "floop:bloop:loop:coop:soop"
my $var1 = shift # floop
my $var2 = shift # bloop
my @arry = @_ # The rest is the array passed.
但是,如果您传入多个数组或哈希值,事情就会崩溃。所有元素都合并为一个由@_
表示的标量列表。
munge_two_arrays ( @foo, @bar );
sub munge_two_arrays {
# Problem! Elements of both arrays are in @_.
# How do I separate them out?
}
因此,通常不传入整个数组,而是传递数组引用:
munge_two_arrays( \@foo, \@bar ); # These are array references
sub munge_two_arrays {
my $array1_ref = shift;
my $array2_ref = shift;
my @array1 = @{ $array1_ref } # Dereference array references to make arrays
my @array2 = @{ $array2_ref } # Dereference array references to make arrays
}
这使得两个数组的值不会合并为单个@_
。