3

What's the difference between %{$var} and %$var? I tried this code but there's error:

each on reference is experimental at test.pl line 21. Type of argument to each on reference must be unblessed hashref or arrayref at test.pl line 21.

use feature 'say';

%HoH = (
    1 => {
        husband   => "fred",
        pal       => "barney",
    },
    2 => {
        husband   => "george",
        wife      => "jane",
        "his boy" => "elroy",
    },
    3 => {
        husband   => "homer",
        wife      => "marge",
        kid       => "bart",
    },
);

for ($i = 1; $i <= 3; $i++) {
    while ( ($family, $roles) = each %$HoH{$i} ) {
        say "$family: $roles";
    }
}

But this code works fine:

use feature 'say';

%HoH = (
    1 => {
        husband   => "fred",
        pal       => "barney",
    },
    2 => {
        husband   => "george",
        wife      => "jane",
        "his boy" => "elroy",
    },
    3 => {
        husband   => "homer",
        wife      => "marge",
        kid       => "bart",
    },
);

for ($i = 1; $i <= 3; $i++) {
    while ( ($family, $roles) = each %{$HoH{$i}} ) {
        say "$family: $roles";
    }
}
stenlytw
  • 938
  • 13
  • 18

2 Answers2

7

With %$HoH{$i} you make a hash reference of $HoH, while with %{$HoH{$i}} you make a hash reference of $HoH{$i}, which is what you want... And, use strict on your code :-)

MarcoS
  • 17,323
  • 24
  • 96
  • 174
  • Yes I usually use strict in my code. It's just for testing purpose. :D. Thanks for your answer. :) – stenlytw Apr 26 '16 at 10:04
  • 2
    @bounces, even in testing you must use it! The error when using strict in your source is quite different: `Global symbol "$HoH" requires explicit package name` and that would have given you the answer to your question. – LaintalAy Apr 26 '16 at 10:10
  • @eballes But there's still an error `each on reference is experimental` with use strict. – stenlytw Apr 26 '16 at 10:13
  • 1
    @bounces: `keys on reference` is expertimental *before* perl 1.14: if you can't upgrade, you can shut up that warning with the line `no warnings 'experimental';` just before the `each`... – MarcoS Apr 26 '16 at 12:15
  • @MarcoS I'm using Perl 5.22. Btw did you mean before perl 5.14? – stenlytw Apr 26 '16 at 13:21
  • Yes, sorry, 5.14... :-( – MarcoS Apr 26 '16 at 13:26
  • But, if you're using 5.22, and get that warning, my comment is wrong, sorry... Did you try the "no warning experimental'" pragma, nonetheless? – MarcoS Apr 26 '16 at 13:28
  • Yes I tried it. The `each on reference is experimental` message disappear if I add `no warnings 'experimental';` – stenlytw Apr 26 '16 at 13:33
2

Its due to the different precedence levels of resolving the hash vs subscripting the hash. It works with the second version - %{ $HoH{$i} } - because you are unambiguously stating that the value returned by the lookup of $HoH{$i} is itself, a hashref.

Whereas %$HoH{$i} is interpreted as %{ $HoH }{$i} - ie. the subscripting is happening after the expression $HoH is interpreted as a hashref - which it isn't. %HoH is a hash but $HoH is not used - i.e. it's undefined.

Marty
  • 2,788
  • 11
  • 17