Как передать хэш по ссылке в perl
Я знаю, что это должно быть легко найти в google, не говоря уже о тривиальном использовании perl, но я пробовал много решений, которые я нашел, и до сих пор ни одно из них не дает ожидаемого поведения. По сути, я пытаюсь вызвать подпрограмму, вернуть ссылку на хэш из этой подпрограммы, передать ссылку на этот хэш другой подпрограмме, а затем распечатать содержимое этого хэша с помощью кода, подобного следующему:
#!/usr/bin/perl
my $foo = make_foo();
foreach $key (sort keys %$foo) {
print "2 $key $$foo{$key}n";
}
print_foo(%foo);
sub print_foo
{
my %loc = ???;
foreach $key (sort keys %loc}) {
print "3 $key $loc{$key}n";
}
}
sub make_foo
{
my %ret;
$ret{"a"} = "apple";
foreach $key (sort keys %ret) {
print "1 $key $ret{$key}n";
}
return %ret;
}
может кто-нибудь сказать мне, лучший способ сделать это (через подпрограммы) без создания дополнительной копии хеш? Решения, которые я пробовал, не распечатали никаких строк, начинающихся с "3".
3 ответов
вы должны вытащить параметры в качестве ссылки, а затем разыменовать его:
sub print_foo
{
my ($loc) = @_;
foreach my $key (sort keys %$loc) {
print "3 $key $loc->{$key}\n";
}
}
всякий раз, когда вы делаете ссылку, вы должны явно разыменовать ее. Кроме того, будьте осторожны, что любые изменения в ссылке изменят оригинал. Если вы хотите избежать изменения оригинала, вы можете либо передать хэш в список:
print_foo(%foo); # flattens the hash to a list and passes it in through @_
sub print_foo
{
my (%loc) = @_; # load the hash from the list
foreach my $key (sort keys %loc) {
print "3 $key $loc{$key}\n";
}
}
или скопируйте хэш-ссылку в новый хэш:
sub print_foo
{
my ($ref_loc) = @_; # changes to %$ref_loc will change %foo
my %loc = %$ref_loc; # COPY, changes to %loc do not change %foo
foreach my $key (sort keys %loc}) {
print "3 $key $loc{$key}\n";
}
}
все остальное хорошо, поэтому я просто сосредоточусь на print_foo...
sub print_foo
{
my %loc = %{shift @_};
foreach $key (sort keys %loc) {
print "3 $key $loc{$key}\n";
}
}
FYI, вам нужно понять, что %loc теперь является копией хэша (я задал вопрос, который объясняет это здесь:путаница в правильном использовании разыменования в Perl ). Чтобы избежать копирования...
sub print_foo
{
my $loc = shift @_;
foreach $key (sort keys %$loc) {
my $val = $loc->{$key}
print "3 $key $val\n";
}
}
вы хотите преобразовать это из ссылки в хэш, например:
my %loc = %{@_[0]};
или
my %loc = %{shift};
вы также можете сохранить его в качестве ссылки:
my $locref = shift;
foreach $key (sort keys %$locref}) {
print "3 $key $locref->{$key}\n";
}
эту информацию можно найти, введя perldoc perlref
в командной строке.