Perl:Sub的论点解释

时间:2014-02-05 01:46:04

标签: perl function arguments shift

在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会替换参数数组而不是写入(如预期的那样)?

2 个答案:

答案 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
}

这使得两个数组的值不会合并为单个@_