如何使用散列作为Perl中子例程的参数?

时间:2009-06-03 13:33:46

标签: perl hash reference

我有一个正在进行一些计算的函数,然后将一些属性传递给另一个子例程,如下所示:

sub get_result {
    my $id = 1;     
    my %diet = ( result  => 28, 
                 verdict => 'EAT MORE FRUIT DUDE...'     
               );

    my %iq = ( result   => 193, 
               verdict => 'Professor Einstien'   
             );           
    print_result($id, %diet, %iq);
}

sub print_result {     
    my $id = shift;     
    my %d  = @_;     
    my %i  = @_;     

    print "IQ: $id\n";     
    print "DIET RESULT: $d{result}\n";     
    print "DIET VERDICT: $d{verdict}\n";     
    print "IQ RESULT: $i{result}\n";     
    print "IQ VERDICT: $i{verdict}\n";     
}     

我的问题是(DIET RESULT,DIET VERDICT)和(IQ SCORE,IQ RESULT)中打印的结果都是相同的。好像变量%d和%i正在填充相同的变量。任何想法为什么会这样?

如果我尝试移动所有三个变量,那么:

my $id = shift;     
my %d  = shift;     
my %i  = shift; 

我收到以下错误:

Odd number of elements in hash assignment

4 个答案:

答案 0 :(得分:25)

当您将数组(或散列)传递给子例程时,子例程将获得值(或键值对)的列表。这就是为什么你不能传递两个数组(或两个哈希),因为子程序不知道第一个数组的结束位置和第二个数组的开始位置。

要解决此问题,您应该传入引用:

my %hash1 = ( foo => 'bar' );
my %hash2 = ( bar => 'baz' );
subroutine( \%hash1, \%hash2 );

sub subroutine {
    my ( $hashref1, $hashref2 ) = @_;
    print $hasref1->{foo}, $hashref2->{bar};
}

PS:除了概念问题,您的代码还具有以下功能:

my %d  = @_;     
my %i  = @_;     

如果%d和%i都被分配了相同的值,那么它们在之后相同时不应该出乎意料。

答案 1 :(得分:5)

您可能需要查看我的书Intermediate Perl,其中约三分之一涉及参考资料以及如何使用它们。这包括将复杂的数据结构传递到子例程以及引用使您的生活更轻松的其他方式。 :)

some_sub( \%hash );
some_sub( { key => 'value' } );
some_sub( $hash_ref );

sub some_sub {
    my( $hash_ref ) = @_;

    ...
    }

答案 2 :(得分:3)

当您传入%diet%iq时,它们都会变为arg数组,因此在print_result中,%d包含%diet中的所有项目}和%iq

要解决此问题,请使用%diet%iq参考

print_result($id, \%diet, \%iq);

然后在print_result

my $id = shift;
my %d  = %{+shift};
my %i  = %{+shift};

答案 3 :(得分:0)

use strict;
use warnings;

sub get_result {

  ...

  print_result( $id, \%diet, \%iq );
  # or
  print_result( $id, {%diet}, {%iq} );
}


sub print_result{
  my( $id, $diet_h, $iq_h ) = @_;
  my %diet = %$diet_h;
  my %iq = %$iq_h;

  ...

}

或者:

use strict;
use warnings;

sub print_result($\%\%);

sub get_result{

  ...

  print_result($id, %diet, %iq);
}

sub print_result($\%\%){
  my( $id, $diet_h, $iq_h ) = @_;
  my %diet = %$diet_h;
  my %iq = %$iq_h;

  ...

}