Как передать хеш по ссылке в perl - PullRequest
10 голосов
/ 13 декабря 2011

Я знаю, что это должно быть легко доступно для поиска в 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 ]

10 голосов
/ 13 декабря 2011

Вы должны использовать параметры в качестве ссылки и затем разыменовывать их:

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";
    }
}
3 голосов
/ 13 декабря 2011

Все остальное хорошо, так что я просто сконцентрируюсь на print_foo ...

sub print_foo
{
    my %loc = %{shift @_};
    foreach $key (sort keys %loc) {
        print "3 $key $loc{$key}\n";
    }
}

К вашему сведению, вы должны понимать, что% loc теперь является КОПИЕЙ хэша (я задал вопрос, который объясняет это здесь: Путаница с правильным использованием разыменования в Perl ). Чтобы не делать копию ...

sub print_foo
{
    my $loc = shift @_;
    foreach $key (sort keys %$loc) {
        my $val = $loc->{$key}
        print "3 $key $val\n";
    }
}
0 голосов
/ 13 декабря 2011

Вы хотите преобразовать это из ссылки в хеш следующим образом:

my %loc = %{@_[0]};

или

my %loc = %{shift};

Вы также можете сохранить его как ссылку:

my $locref = shift;
foreach $key (sort keys %$locref}) {
    print "3 $key $locref->{$key}\n";
}

Эту информацию можно найти, набрав perldoc perlref в командной строке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...