Вы можете легко сделать это с помощью ссылок и фрагментов хеша:
sub takes_hashref {
my $hashref = shift;
my ($one, $two, $three, $four, $five) = \@$hashref{
qw(one two three four five)
};
print "one: $$one, two: $$two, three: $$three, ",
"four: $$four, five: $$five\n";
$_++ for $$one, $$three, $$five;
}
my %hash = qw(one 1 two 2 three 3 four 4 five 5);
takes_hashref \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7
@$hashref{qw(x y z)}
- это фрагмент хеша, который возвращает список значений. Предварительное добавление \
принимает ссылку на каждое значение и возвращает список ссылок. Затем это присваивается вашим лексическим переменным. Когда вы используете каждую переменную, удвойте символ, чтобы разыменовать его: $$var
. Поскольку эти переменные содержат ссылки на поля хеша, вы можете присвоить им: $$var = 'new val'
, и присвоение изменит исходный хеш. Если вас не волнуют изменения переменных, распространяющихся обратно в хеш, вы можете опустить \
в срезе хэша и двойной символ для всех переменных.
Если вы просто хотите создать более короткий псевдоним для работы, вы можете локализовать %_
в своей подпрограмме:
sub takes_hashref2 {
my $hashref = shift;
local *_ = \%$hashref;
print "one: $_{one}, two: $_{two}, three: $_{three}, ",
"four: $_{four}, five: $_{five}\n";
$_++ for @_{qw(one three five)};
}
my %hash = qw(one 1 two 2 three 3 four 4 five 5);
takes_hashref2 \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref2 \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref2 \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7
В строке local *_ = \%$hashref
псевдонимы %_
к хешу в $hashref
. Часть \%
не обязательна, но выдает ошибку, если значение в $hashref
не является хешем. Это просто более короткий способ написания:
die 'not a hash' unless ref $hashref eq 'HASH';
local *_ = $hashref;
И вы можете написать это в одной строке как:
local *_ = \%{shift @_};