如何在perl中通过引用传递散列

如何在perl中通过引用传递散列,perl,Perl,我知道这应该很容易在google上搜索,更不用说perl的一个小用途了,但我已经尝试了许多我找到的解决方案,到目前为止,没有一个给出预期的行为。本质上,我试图调用一个子例程,从该子例程返回对散列的引用,将对该散列的引用传递给另一个子例程,然后通过类似以下代码打印该散列的内容: #!/usr/bin/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”开头的行。

您希望将其从引用转换为散列,如下所示:

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

您也可以将其作为参考:

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

通过在命令行中键入
perldoc perlref
可以找到此信息。

您必须将参数作为参考输入,然后取消引用:

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";
    }
}

其他一切都很好,所以我只想专注于印刷品

sub print_foo
{
    my %loc = %{shift @_};
    foreach $key (sort keys %loc) {
        print "3 $key $loc{$key}\n";
    }
}
仅供参考,您需要意识到%loc现在是散列的副本(我问了一个问题,解释了这一点:)。为了避免复制

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

另外,我强烈建议您在所有代码的顶部开始使用
use strict
。您需要更改
foreach
行,以使用
my
声明变量,但这将为调试简单的打字错误省去许多麻烦。单元素切片最好写成
%{$\u0]}
%{shift}
是指名为
shift
的哈希变量,您可能指的是
%{+shift}
%{shift@}
。命名循环变量应该是词法
foreach my$key…
sub print_foo
{
    my $loc = shift @_;
    foreach $key (sort keys %$loc) {
        my $val = $loc->{$key}
        print "3 $key $val\n";
    }
}