Как передать хеш в подпрограмму? - PullRequest
19 голосов
/ 04 февраля 2011

Нужна помощь в выяснении, как это сделать.Мой код:

my %hash;
$hash{'1'}= {'Make' => 'Toyota','Color' => 'Red',};
$hash{'2'}= {'Make' => 'Ford','Color' => 'Blue',};
$hash{'3'}= {'Make' => 'Honda','Color' => 'Yellow',};


&printInfo(%hash);

sub printInfo{
   my (%hash) = %_;
   foreach my $key (keys %_{       
    my $a = $_{$key}{'Make'};   
    my $b = $_{$key}{'Color'};   
    print "$a $b\n";
    }
}

Ответы [ 5 ]

33 голосов
/ 04 февраля 2011

Самый простой способ, который может привести к проблемам при развитии кода, - просто назначить массив по умолчанию @_ (который содержит все пары ключ-значение в виде четного списка) хешу%, который затем перестраивается соответственно. Итак, ваш код будет выглядеть так:

sub printInfo {
   my %hash = @_;
   ...
}

Лучшим способом было бы передать хеш как ссылку на подпрограмму. Таким образом, вы все равно можете передать больше параметров в подпрограмму.

printInfo(\%hash);
sub PrintInfo {
   my %hash = %{$_[0]};
   ...
}

Введение в использование ссылок в Perl можно найти в perlreftut

8 голосов
/ 04 февраля 2011

Ты очень, очень близко. Для передачи хэшей нет %_, оно должно быть передано в @_. К счастью, хэши назначаются с использованием контекста списка, поэтому

sub printInfo {
   my %hash = @_;
   ...
}

заработает!

Также обратите внимание, что использование & перед вызовом подпрограммы в большинстве случаев было излишним, поскольку, по крайней мере, в Perl 5.000. В эти дни вы можете вызывать подпрограммы Perl, как и на других языках, используя только имя и аргументы. (Как указывает @mob в комментариях, в некоторых случаях это все еще необходимо; см. perlsub , чтобы понять это подробнее, если интересно).

6 голосов
/ 04 февраля 2011

Я верю, что вы хотите

my %hash;
$hash{'1'}= {'Make' => 'Toyota','Color' => 'Red',};
$hash{'2'}= {'Make' => 'Ford','Color' => 'Blue',};
$hash{'3'}= {'Make' => 'Honda','Color' => 'Yellow',};

printInfo(%hash);

sub printInfo{
   my %hash = @_;
   foreach my $key (keys %hash){       
    my $a = $hash{$key}{'Make'};   
    my $b = $hash{$key}{'Color'};   
    print "$a $b\n";
   }
}

В строке printInfo(%hash) %hash раскрывается в список с чередующимися парами ключ-значение.

В printInfo, @_ - это список, который при присвоении %hash снова создает ключи с соответствующим значением из чередующихся элементов в списке.

5 голосов
/ 20 августа 2013

Лучший способ передачи хешей и массивов - ссылка .Ссылка - это просто способ говорить о сложной структуре данных как о единой точке данных - о чем-то, что может быть сохранено в скалярной переменной (например, $foo).

Читатьна ссылках , чтобы вы понимали, как создать ссылку и разыменование ссылку для возврата исходных данных.

Само основы: вы предшествуете своим даннымструктура с обратной косой чертой для получения ссылки на эту структуру.

my $hash_ref   = \%hash;
my $array_ref  = \@array;
my $scalar_ref = \$scalar;   #Legal, but doesn't do much for you...

Ссылка - это область памяти исходной структуры (плюс подсказка о структуре):

print "$hash_ref\n";

Напечатает что-то вроде:

HASH(0x7f9b0a843708)

Чтобы вернуть ссылку в пригодный для использования формат, вы просто помещаете ссылку в правильный символ перед:

my %new_hash = %{ $hash_ref };

Вы должны узнать об использовании ссылок, поскольку именно так вы можете создавать чрезвычайно сложные структуры данных в Perl и как работает объектно-ориентированный Perl.


Допустим, вы хотите пройти трихеши к вашей подпрограмме.Вот три хеша:

my %hash1 = ( this => 1, that => 2, the => 3, other => 4 );
my %hash2 = ( tom => 10, dick => 20, harry => 30 );
my %hash3 = ( no => 100, man => 200, is => 300, an => 400, island => 500 );

Я создам для них ссылки

my $hash_ref1 = \%hash1;
my $hash_ref2 = \%hash2;
my $hash_ref3 = \%hash3;

А теперь просто передам ссылки:

mysub ( $hash_ref1, $hash_ref2, $hash_ref3 );

Ссылки скалярные данные, поэтому нет проблем с передачей их в мою подпрограмму:

sub mysub {
    my $sub_hash_ref1  = shift;
    my $sub_hash_ref2  = shift;
    my $sub_hash_ref3  = shift;

Теперь я просто разыменовываю их, и моя подпрограмма может их использовать.

    my %sub_hash1 = %{ $sub_hash_ref1 };
    my %sub_hash2 = %{ $sub_hash_ref2 };
    my %sub_hash3 = %{ $sub_hash_ref3 };

Вы можете увидеть, на что ссылается ссылка, используя команду ref :

my $ref_type = ref $sub_hash_ref;    # $ref_type is now equal to "HASH"

Это полезно, если вы хотите убедиться, что вы передали правильный типструктуры данных.

sub mysub {
    my $hash_ref = shift;

    if ( ref $hash_ref ne "HASH" ) {
        croak qq(You need to pass in a hash reference);
    }

Также обратите внимание, что это ссылки на память, поэтому изменение ссылки изменит исходный хеш:

my %hash = (this => 1, is => 2, a => 3 test => 4);
print "$hash{test}\n";   # Printing "4" as expected
sub mysub ( \%hash );    # Passing the reference
print "$hash{test}\n";   # This is printing "foo". See subroutine:


sub mysub { 
    my $hash_ref = shift;

    $hash_ref->{test} = "foo";    This is modifying the original hash!
}

Это может быть хорошо - это позволяет вамизменить данные, переданные в подпрограмму, или неверные - это позволяет вам непреднамеренно изменить данные, переданные в исходную подпрограмму.

3 голосов
/ 04 февраля 2011

Вы можете передать их как

  1. Список аргументов do_hash_thing( %hash )
  2. Ссылка на хеш в списке аргументов `do_hash_thing (@args_before, \% hash, @args_after)
  3. В качестве ссылки прототип , работающий как keys и другие хеш-операторы.

Список работает так:

sub do_hash_thing {
    my %hash = @_;
    ...
}

do_hash_thing( %hash );

Это также позволяет вам «транслировать» хеш-аргументы:

do_hash_thing( %hash_1, %hash_2, parameter => 'green', other => 'pair' );

По ссылке работает так:

sub do_hash_thing { 
    my $hash_ref = shift;
    ...
}

do_hash_thing( \%hash, @other_args );

Здесь по прототипу (\%@).Прототип заставляет Perl искать хэш в первом аргументе и передавать его по ссылке.

sub do_hash_thing (\%@) { 
    my $hash_ref = shift;
    ...
}

do_hash_thing( %hash => qw(other args) );
# OR
do_hash_thing %hash => qw(other args);

Предупреждение: прототипы не работают с методами.

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