Perl将参数传递给子例程不起作用
我试图将参数传递给perl子例程,并且无论出于何种原因,子例程中的参数都是空的。Perl将参数传递给子例程不起作用
...
...
...
print "Passing arguments $a, $b, $c, $d \n";
beforeEnd($a, %b, $c, $d);
sub beforeEnd() {
my ($a, %b, $c, $d) = @_;
print "a is $a, b is $b, c is $c, d is $d \n";
}
打印语句的输出给了我一个想法,即某些错误。奇怪的部分?前两个参数正确传递。
> Passing arguments 1, (1,2,3), 2, 3
> a is 1, b is (1,2,3), c is , d is
任何帮助将不胜感激。
因为当你将参数传入或传出子程序时,任何散列和数组都被平坦地砸碎。
您正在分配到%b
这将吞噬任何参数。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
sub test1 {
my ($first, @rest, $last) = @_;
print Dumper \@rest;
print "First = $first, last = $last, rest = @rest\n";
}
sub test2 {
my ($first, $second) = @_;
print "@$first ; @$second";
}
test1 (1, 2, 3, 4);
test2 ([1,2], [ 3,4]);
my @list1 = (1,2,3,4);
my @list2 = (5,6,7,8);
test1 (@list1, @list2);
test2 (\@list1, \@list2);
如果你想保持数组或散列完整,你需要通过引用或作为最后一个参数传递它们。
你也可能会得到一个警告,如果你打开strict
和warnings
在这里 - 这是它强烈推荐的原因之一 - 因为$b
和%b
是不一样的。您还会收到关于奇数分配的警告:
Odd number of elements in hash assignment at line 5.
Use of uninitialized value $b in print
将参数传递给Perl子例程时,它们被平化为一个由@_
表示的单个列表。从概念上讲,这意味着如果你没有传递对数组或哈希的引用,你将会“丢失”一些数据。 “丢失”并不完全正确,因为所有的数据都在那里;它只是不在你期望的变量中。这方面的一个例子是:
sub f {
my (@a, @b) = @_;
say 'a: ' . join(', ', @a);
say 'b: ' . join(', ', @b);
}
f(qw(1 2 3), qw(a b c));
您将得到以下输出:
a: 1, 2, 3, a, b, c
b:
发生这种情况,因为第一阵列@a
消耗的所有值从@_
和那里没有更多的时间可以存储在@b
。 beforeEnd子例程中的散列同样如此。 $c
和$d
的值存储在%b
的内部。作为一个例子,因为我看不到变量的值,如果你通过
beforeEnd(1, (a => 1, b => 2), 'c', 3);
你的子里面,你得到的东西是这样的:
$a = 1
%b = (a => 1, b => 2, c => 3)
$c = undef
$d = undef
你可以通过引用来解决这个你hash%b:
beforeEnd($a, \%b, $c, $d);
子例程接受标量列表作为参数。如果传递数组或散列,则会传递数组或散列的内容。这意味着,
f($a, %b, $c, $d)
相同
f($a, $b_key_1, $b_val_1, $b_key_2, $b_val_2, $b_key_3, $b_val_3, $c, $d);
多少在@_
标量的应分配给%b
? Perl的保持它的简单和分配所有剩余的标量,从而
my ($a, %b, $c, $d) = @_;
比
my $a = $_[0]; # The first argument
my %b = @_[1..$#_]; # All but the first argument
my $c;
my $d;
,如果你传递给散列的引用这是最好真的没有什么不同。这避免了这个问题,而且效率更高。
use Data::Dumper qw(Dumper);
sub beforeEnd {
my ($a, $b, $c, $d) = @_;
local $Data::Dumper::Terse = 1;
print "a is $a, b is ".Dumper($b).", c is $c, d is $d \n";
}
beforeEnd($a, \%b, $c, $d);
题外话你的代码注释:
你不得不表示没有参数的原型,预计
()
,但是你指望四强。摆脱那个原型。您应该避免使用
$a
和$b
作为变量,因为它可能与sort
相关。
参数只能在子程序中作为标量变量列表传递。
无论何时将参数传递给子例程,我们都需要传递散列引用(或数组,对象)。 ... ... ... print“传递参数$ a,$ b,$ c,$ d \ n”; ($ a,\%b,$ c,$ d);
sub beforeEnd() {
my ($a, $b, $c, $d) = @_;
print "a is $a, b is %$b, c is $c, d is $d \n";
}
您正在传递'%b',但是正在打印'$ b'。 – Barmar 2015-03-30 19:22:08
赋值中的列表变量将接收函数的所有其余参数。 – Barmar 2015-03-30 19:23:12
如果要传递列表而不将其作为单独的参数传播出去,则应该使用数组引用。 – Barmar 2015-03-30 19:24:37