2014-11-21 42 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