Как передать хэш подпрограмме?

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

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";
    }
}

Ответы

Ответ 1

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

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

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

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

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

Ответ 2

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

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

заставит его работать!

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

Ответ 3

Я считаю, что вы хотите

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

Ответ 4

Лучший способ передать хэши и массивы - ссылка. Ссылка - это просто способ рассказать о сложной структуре данных как о единственной точке данных - то, что может быть сохранено в скалярной переменной (например, $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)

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

my %new_hash = %{ $hash_ref };

Вы должны узнать об использовании ссылок, так как это позволяет создавать чрезвычайно сложные структуры данных в Perl и как работает Object Oriented 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!
}

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

Ответ 5

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

  • Список аргументов do_hash_thing( %hash )
  • Ссылка на хэш в списке аргументов `do_hash_thing (@args_before,\%hash, @args_after)
  • Как ссылка прототипом, работающим как 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);

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