2014-11-21 127 views
0

我有一个深度嵌套结构的散列。预先不知道嵌套的级别。但是每个级别都有两个属性“实例”和另一个“依赖关系”的散列。所以这是一种看起来像递归的散列。Perl:从子程序返回hashref

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 

我做错了什么!?!?

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

+1

您显示的代码没有任何问题。复制并粘贴,添加导入,删除c样式注释(使用#for perl注释)并按预期打印。你能显示你的确切代码吗?你使用严格和warniings? – Nate 2014-11-21 01:24:37

+0

我怀疑当你尝试*使用hashref;显示你在那里试着做什么。 http://perlmonks.org?node=References+quick+reference有一些有用的规则来弄清楚如何使用参考 – ysth 2014-11-21 01:40:10

回答

2

您正在返回foreach所评估的值(作为子的最后一个声明)。这并不奇怪,这不是一个参考。

&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}更具可读性。
+0

完美。我确实意识到回报是问题所在。但是没想到从foreach循环返回,这实际上是在子例程中执行的最后一个语句。 – shikhanshu 2014-11-21 04:23:47

+0

感谢您的帮助!子程序调用和做什么?我一直使用它们。我读这个链接获取更多的解释:http://stackoverflow.com/questions/1347396/when-should-i-use-the-to-call-a-perl-subroutine,我不会再使用它了! – shikhanshu 2014-11-21 17:43:38

+0

导致原型被忽略。 – ikegami 2014-11-21 18:01:47

0

哎哟。我假定递归函数中的“return”语句立即脱离递归并返回值。它没有。所以,当递归尽可能深入,并开始回来,没有什么可以回来了。

我通过在子例程之外设置一个全局来解决这个问题,并且在子例程中,我简单地将此全局设置为子哈希。

这符合我的目的!

+0

流,坏。没有理由为全球。 – ikegami 2014-11-21 04:21:36