Как передать хэш по ссылке в 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 в командной строке.