2015-03-30 75 views
0

我试图将参数传递给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 

任何帮助将不胜感激。

+0

您正在传递'%b',但是正在打印'$ b'。 – Barmar 2015-03-30 19:22:08

+0

赋值中的列表变量将接收函数的所有其余参数。 – Barmar 2015-03-30 19:23:12

+0

如果要传递列表而不将其作为单独的参数传播出去,则应该使用数组引用。 – Barmar 2015-03-30 19:24:37

回答

2

因为当你将参数传入或传出子程序时,任何散列和数组都被平坦地砸碎。

您正在分配到%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); 

如果你想保持数组或散列完整,你需要通过引用或作为最后一个参数传递它们。

你也可能会得到一个警告,如果你打开strictwarnings在这里 - 这是它强烈推荐的原因之一 - 因为$b%b是不一样的。您还会收到关于奇数分配的警告:

Odd number of elements in hash assignment at line 5. 
Use of uninitialized value $b in print 
1

将参数传递给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); 
1

子例程接受标量列表作为参数。如果传递数组或散列,则会传递数组或散列的内容。这意味着,

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相关。

0

参数只能在子程序中作为标量变量列表传递。

无论何时将参数传递给子例程,我们都需要传递散列引用(或数组,对象)。 ... ... ... 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"; 
} 
相关问题