在 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 会替换参数数组而不是写入其中(如预期的那样)?
只能将标量列表传递给子例程(这就是它们可以返回的全部内容)。毕竟,参数以数组的形式呈现给子进程 (
@_
),而数组只能包含标量。
您可以(效率低下)在子中重新创建数组
sub foo {
my @bars = @_;
say for @bars;
}
foo(@bars);
或者您可以传递对数组的引用
sub foo {
my ($bars) = @_;
say for @$bars;
}
foo(\@bars);
您需要了解 shift 的作用。
shift
/unshift
命令对与pop
/push
命令对并行。所有这些命令都在arrays上运行。默认情况下,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
}
这可以防止两个数组的值合并为一个
@_
。