Perl传递子程序的参数不起作用

时间:2015-03-30 19:17:42

标签: perl parameters subroutine

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

非常感谢任何帮助。

4 个答案:

答案 0 :(得分: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 :(得分:1)

当参数传递给Perl子例程时,它们被展平为由@_表示的单个List。从概念上讲,这意味着如果你没有传递对数组或哈希的引用,你将失去"一些数据。 "输"是不完全正确的,因为所有的数据仍然存在;它只是不在你期望的变量中。这方面的一个例子可能是:

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 

您可以通过将引用传递给哈希值b来解决此问题:

beforeEnd($a, \%b, $c, $d);

答案 2 :(得分: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有关。

答案 3 :(得分:0)

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

每当将参数传递给子例程时,我们都需要传递散列(或数组,对象)的引用。 ... ... ...     print“传递参数$ 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";
}