Этот код работает:
#!/bin/perl -w
use strict;
sub PrintAA
{
my($test, %aa) = @_;
print $test . "\n";
foreach (keys %aa)
{
print $_ . " : " . $aa{$_} . "\n";
}
}
my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );
PrintAA("test", %hash);
Ключевым моментом является использование контекста массива в 'операторе' my () в функции.
Что на самом деле делает бизнес контекста массива?
Вкратце, это заставляет его работать правильно.
Это означает, что первое значение в массиве аргументов @_
присвоено $test
, а остальные элементы назначены хэшу %aa
. Учитывая то, как я это назвал, в @_
есть нечетное количество элементов, поэтому, как только первый элемент назначен на $test
, есть четное количество элементов, доступных для присвоения %aa
, с первым Элемент каждой пары является ключом (в моем примере это «aaa», «bbb», «ccc»), а второй является соответствующим значением.
Можно было бы заменить %aa
на @aa
, в этом случае в массиве будет 6 элементов. Можно также заменить %aa
на $aa
, и в этом случае переменная $aa
будет содержать значение 'aaa', а остальные значения в @_
будут игнорироваться присваиванием.
Если вы опустите скобки вокруг списка переменных, Perl откажется компилировать код.
Один из альтернативных ответов показал обозначение:
my $test = shift;
my(%aa) = @_;
Это в значительной степени эквивалентно тому, что я написал; разница состоит в том, что после двух операторов my
@_
содержит только 6 элементов в этом варианте, тогда как в одиночной версии my
оно все еще содержит 7 элементов.
В SO есть определенно другие вопросы о контексте массива.
На самом деле, я не спрашивал о my($test, %aa) = @_;
Я спрашивал о my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );
против my %hash = { 'aaa' => 1, ... };
Разница в том, что нотация {...} генерирует хеш-ссылку, а нотация (...) генерирует список, который отображается на хеш (в отличие от хеш-ссылки). Точно так же [...] генерирует массив ref, а не массив.
Действительно, измените основной код так, чтобы он читал: my (% hash) = {...}; и вы получаете ошибку во время выполнения (но не во время компиляции) - относитесь к номерам строк с осторожностью, так как я добавил альтернативные кодировки в свой файл:
Reference found where even-sized list expected at xx.pl line 18.
...
Use of uninitialized value in concatenation (.) or string at xx.pl line 13.