Perl:从子例程返回hashref

时间:2014-11-21 01:03:16

标签: perl hash subroutine hashref

我有一个深层嵌套结构的哈希。嵌套的水平在前面是未知的。但是每个级别都有两个属性“instance”和另一个“依赖”哈希。所以它是一种递归的哈希。

my $HASH = {
    "top"=> {
        "instance" => "top_instance",
        "dependencies" => {
            "sub_block1" => {
                "instance" => "sub_block1_instance",
                "dependencies" => {}
            },
            "sub_block2" => {
                "instance" => "sub_block2_instance",
                "dependencies" => {
                    "sub_block3" => {
                        "instance" => "sub_block3_instance",
                        "dependencies" => {}
                    }
                }
            }
        }
    }
};

我有一个子例程,它接受用户定义的字符串,并从指定的层次结构层返回一个内部哈希值。

示例,如果用户指定“sub_block2”,则子例程应返回此哈希:

{
    "sub_block2" => {
        "instance" => "sub_block2_instance",
        "dependencies" => {
            "sub_block3" => {
                "instance" => "sub_block3_instance",
                "dependencies" => {}
            }
        }
    }
}

这是我的子程序:

sub get_starting_point {
    my $string = shift;
    my $config = shift;
    foreach my $key (keys %$config) {
        if($key ne $string) {
            # if current key is not what user asked for, recurse into next level of hierarchy
            if (exists $$config{$key}{dependencies}) {
                &get_starting_point($$config{$key}{dependencies});
            }
        } else {
            # we found the key, return the hash under this hierarchy
            my $tempHash = {$key => $$config{$key}};
            print ref($tempHash); # correctly prints HASH
            print Dumper($tempHash); # correctly prints out the sub-hash
            return $tempHash; # I am expecting this return value to be a hash-ref
        }
    }
}

正如你所看到的,这是一个递归函数,它继续深入哈希,直到它遇到一个与参数匹配的键并返回该键下的完整子哈希。

这就是我调用这个子程序的方式。

my $subHash = get_starting_point("sub_block2",$HASH);
print ref($subHash); # is not a ref
print Dumper($subHash); # prints nothing

我做错了什么!?!?

编辑:用我的确切问题更新了问题。看起来像我之前按预期使用的一个简单示例。

2 个答案:

答案 0 :(得分:2)

您将返回foreach评估的值(由于是sub的最后一个语句)。这不是一个参考,这并不奇怪。

&get_starting_point($$config{$key}{dependencies});

应该是

my $rv = get_starting_point($config->{$key}{dependencies});
return $rv if $rv;

最后添加return undef;而不是依赖foreach返回错误的内容。

sub get_starting_point {
    my $string = shift;
    my $config = shift;
    for my $key (keys %$config) {
        if ($key eq $string) {
            return { $key => $config->{$key} };
        }

        if ($config->{$key}{dependencies}) {
           my $rv = get_starting_point($config->{$key}{dependencies});
           return $rv if $rv;
        }
    }

    return undef;
}

注意:

  • 请不要使用&为您的子来电添加前缀。你甚至知道那是做什么的吗?
  • 大多数人认为$config->{$key}$$config{$key}更具可读性。

答案 1 :(得分:0)

哎哟。我假设递归函数中的“return”语句立即突破递归并返回值。它没有。因此,当递归尽可能深入并开始重新启动时,就没有任何东西可以返回了。

我通过在子例程外部设置全局来解决这个问题,在子例程中,我只是将此全局设置为子哈希。

这符合我的目的!