Guildenstern has asked for the wisdom of the Perl Monks concerning the following question:

This problem hopefully has a simple answer, but I can't find it. I have a hash of hashes. All I'm trying to do right now is print out all of the values to make sure that the hash got populated correctly. No matter what I do, it doesn't work.
First I tried:
my %prochash; # sub call to populate hash for (my $i = 0; $i < $prochash{NumProcessors}; $i++) { foreach (keys ($prochash{'Processor$i'})) { print "$_ : ",$prochash{"Processor$i"}->{$_},"\n"; } }

This yields the error "Type of arg 1 to keys must be hash (not hash element)". Fine.

Next I tried:
foreach (keys %($prochash{'Processor$i'}))
I've seen this notation several times on PM, but it gives me the error "Use of 'keys' without parens ambiguous". *Sigh*

So, my next attempt was:
foreach (keys (%($prochash{'Processor$i'})))
This one gives me the error "Scalar found where operator expected". Rrrrrr

The last error leads me to think that maybe I'm putting the parens in the wrong place, but I can't think of anywhere else they can go. If I take the parens off of around the "keys" part, I get "Missing $ on loop variable".
This is really starting to drive me batty! If it makes any difference, I'm running ActiveState's port of 5.60. Thanks!

Guildenstern
Negaterd character class uber alles!

Replies are listed 'Best First'.
(Ovid) Re: Can't access hash of hashes.
by Ovid (Cardinal) on Sep 07, 2000 at 18:31 UTC
    You need to force the second hash to be evaluated in a hash context. That means enclosing it in %{...} (those are braces, not parens).
    my %prochash; # sub call to populate hash for (my $i = 0; $i < $prochash{NumProcessors}; $i++) { foreach (keys %{$prochash{'Processor$i'}}) { print "$_ : ",$prochash{"Processor$i"}->{$_},"\n"; } }
    Cheers,
    Ovid

    Update: Oy! That's what I get for dashing off a quick answer prior to running to work. I did not say "hash context". I wouldn't say anything like that. Would I? :( Sigh... time to inject more coffee.

      That was the trick! I just couldn't seem to find that information anywhere in Advanced Programming or in the Camel Book.
      So, if I understand this correctly, I could use @{...} to force something to be evaluated in a list context? Very good piece of information - I've now added it to my Perl magnetic poetry in my cube so I can be sure to remember it.

      Guildenstern
      Negaterd character class uber alles!
(jcwren) RE: Can't access hash of hashes.
by jcwren (Prior) on Sep 07, 2000 at 18:44 UTC
    While it's good to know how to display the hashes yourself (for other purposes), for debugging, Data::Dumper is hard to beat. If you haven't checked this out, it's a great time saver. And it beats the heck out writing your own code just to dump the hash or array, then deleting the code.

    A really (stupid) example would be the following. (This uses the object oriented implementation, which is a little more flexible.)
    #!/usr/local/bin/perl -w use strict; use Data::Dumper; { my %prochash = (-a => {-a1 => 1, -a2 => 2}, -b => 2, -c => 'This is + a test'); my $d = new Data::Dumper ([\%prochash], [qw(prochash)]); print $d->Dump (); }
    Gives the nice following output:
    $prochash = { '-b' => 2, '-c' => 'This is a test', '-a' => { '-a2' => 2, '-a1' => 1 } };
    --Chris

    e-mail jcwren
Re: Can't access hash of hashes.
by swiftone (Curate) on Sep 07, 2000 at 18:43 UTC
    This isn't directly an answer, but this is something I do when I have a conglomeration of references that aren't behaving.

    Start by printing the base:

    print $prochash;
    if you get a HASH(gibberish), you'll know it's a hash reference. Then you can print the elements of that:
    foreach my $key (keys %{$prochash}){ print $key,'--',$prochash->{$key},"\n"; }
    In your case, the base is a hash, so:
    foreach my $key( keys %prochash){ print $key, '--', $prochash{$key},"\n"; }
    Which should show a bunch of HASH references.

    Often, while debugging these, I will find that I accidentally slipped in a reference to a reference while passing values betweeen subs. So if $hashref is a reference to a hash, I passed \$hashref, which creates a reference to a scalar (that scalar being a reference to a hash. When this happens, my

    print $hashref;
    gives me SCALAR(0XFFFFF), and I've determined where the problem is introduced.

    I'm sure others will recommend the perl debugger or even not making the mistake in the first place as a solution, but this is the technique I found most useful when learning references, and I still use it now and then when my $value->{key}->{key}->[3]->{key} doesn't work. :)