参数传递给Perl子例程的顺序是否显着?

时间:2015-02-01 02:30:32

标签: perl

参数传递给Perl子例程的顺序是否显着?当我调试以下代码时:

my $loopCounter = 1;
foreach(@authors) {

   my @splitAffiliations = splitAffiliations($params);
   my @foundItems = findAffiliationForAuthor($_, @splitAffiliations, $loopCounter);

   # Process @foundItems

   $loopCounter++;
}

...

sub findAffiliationForAuthor {

   my ($author, @affiliations, $aIndex) = @_;

   ...
} 

我发现变量$loopCounter在调用子例程findAffiliationForAuthor之前有一个值,但在调用后未定义。因此,子程序接收前两个参数的值而第三个参数没有任何值。但是,当我将参数的顺序更改为:

my @foundItems = findAffiliationForAuthor($loopCounter, $_, @splitAffiliations);

保留$loopCounter的值并按预期​​传递子例程。

看起来我必须将所有标量变量放在我的数组变量之前,或者可能不会混合它们。听起来不错吗?

2 个答案:

答案 0 :(得分:5)

当然,订单很重要。

参数按照传递它们的顺序传递,数组参数展平到参数列表中。参数列表在子例程内显示为@_列表的内容。

你实际上不能将数组作为参数传递;它的元素被提取并用任何其他参数推入列表中。

您遇到的问题是因为您处理参数的方式:

my ($author, @affiliations, $aIndex) = @_;

$author按照您的意图获取@_的第一个元素,但@affiliations会覆盖列表的其余部分。然后将值undef存储在$aIndex

只要它是最后一个参数,您就可以将单个数组传递给子例程:

my($first_scalar, $second_scalar, @array) = @_;

如果将多个数组传递给子例程:

foo(@array1, @array2);

两个数组的元素被展平为一个列表,子程序无法知道哪个元素来自哪个数组参数。

您可以将引用传递给数组:

sub foo {
    my ($scalar1, $array_ref1, $scalar2, $array_ref2) = @_;
    # ...
}

然后像这样调用它:

foo(42, \@array1, $some_scalar, \@array2);

答案 1 :(得分:2)

子例程将标量列表作为参数。如果从数组构建参数列表,则将传递数组的内容。

$ perl -E'sub f { say "$_: $_[$_]" for 0..$#_; }  f("a", "b", "c", "d", "e")'
0: a
1: b
2: c
3: d
4: e

$ perl -E'sub f { say "$_: $_[$_]" for 0..$#_; }  @a = ("b"); f("a", @a, "c", "d", "e")'
0: a
1: b
2: c
3: d
4: e

$ perl -E'sub f { say "$_: $_[$_]" for 0..$#_; }  @a = ("b", "c"); f("a", @a, "d", "e")'
0: a
1: b
2: c
3: d
4: e

现在您将参数列表(@_的内容)分配给

($author, @affiliations, $aIndex)

它应该为@affiliations分配多少个标量?你可以说除了第一个和最后一个之外的所有内容,但是你必须为

提出新的规则
my (@a, @b) = @_;

为了简单起见,Perl总是将所有剩余的标量分配给列表中的第一个数组。如果数组是最后一个元素,则可以正常工作,但不是这样。

如果要将数组传递给sub,最好的方法是传递对它的引用。

$ perl -E'sub f { say "$_: $_[$_]" for 0..$#_; }  @a = ("b", "c"); f("a", \@a, "d", "e")'
0: a
1: ARRAY(0x14ff8d0)
2: d
3: e