Как передать хэш подпрограмме?
Нужна помощь в выяснении, как это сделать. Мой код:
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);
Предостережение: прототипы не работают над методами.