【问题标题】:Perl: Sub's arguments explainPerl:Sub 的论点解释
【发布时间】:2014-03-01 06:55:03
【问题描述】:

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

【问题讨论】:

  • 我明白了,但是为什么@data_array 代替@_ 而是写在里面,比如@_[0]=>@data_array; @_[1]=>$other_var
  • @Arkham.vm 它没有。数组被展平,其元素传递给您的子例程并插入到@_
  • @TLP,实际上是同一个替换,只是丢失了一个指向数组的指针。

标签: perl function arguments shift


【解决方案1】:

只能将标量列表传递给子例程(这就是它们可以返回的全部内容)。毕竟,参数是作为数组(@_)呈现给子的,而数组只能包含标量。

您可以(低效地)在 sub 中重新创建数组

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

 foo(@bars);

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

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

 foo(\@bars);

【讨论】:

  • 第二个例子不应该使用foo(\@bars);foo([@bars]);吗?
  • 哎呀,意思是。固定的。 (foo([@bars]) 的效率与第一个 sn-p 相同。)
【解决方案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
}

这可以防止两个数组的值合并到一个 @_ 中。

【讨论】:

  • 谢谢,我不知道要传递多个数组,现在我明白了。
猜你喜欢
  • 2012-09-26
  • 1970-01-01
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2014-09-03
  • 2015-09-08
  • 1970-01-01
相关资源
最近更新 更多