Perl:Sub 的参数解释

问题描述 投票:0回答:2

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

perl function arguments shift
2个回答
6
投票

只能将标量列表传递给子例程(这就是它们可以返回的全部内容)。毕竟,参数以数组的形式呈现给子进程 (

@_
),而数组只能包含标量。

您可以(效率低下)在子中重新创建数组

 sub foo {
    my @bars = @_;
    say for @bars;
 }

 foo(@bars);

或者您可以传递对数组的引用

 sub foo {
    my ($bars) = @_;
    say for @$bars;
 }

 foo(\@bars);

2
投票

您需要了解 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
}

这可以防止两个数组的值合并为一个

@_

© www.soinside.com 2019 - 2024. All rights reserved.