Как я могу использовать хэши в качестве аргументов для подпрограмм в Perl? - PullRequest
7 голосов
/ 03 июня 2009

У меня есть функция, которая выполняет некоторые вычисления, а затем передает некоторые свойства в другую подпрограмму, например:

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 ]

25 голосов
/ 03 июня 2009

Когда вы передаете массив (или хэш) подпрограмме, подпрограмма получит список значений (или пары значений ключей). Вот почему вы не можете передать два массива (или два хэша), потому что подпрограмма не будет знать, где заканчивается первый массив и начинается второй.

Чтобы обойти эту проблему, вы должны вместо этого передать ссылки:

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 обоим присвоено одно и то же значение, то это не должно вызывать удивления, если впоследствии они совпадают.

5 голосов
/ 03 июня 2009

Возможно, вы захотите проверить мою книгу Промежуточный Perl , около трети которой посвящено ссылкам и тому, как с ними работать. Это включает передачу сложных структур данных в подпрограммы, а также другие способы облегчения вашей жизни. :)

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

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

    ...
    }
3 голосов
/ 03 июня 2009

Когда вы передаете %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};
0 голосов
/ 03 июня 2009
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;

  ...

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...