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

So, I just want to do a hash where the value referred to by each key is a reference to another hash.
#!/usr/bin/perl use strict; use warnings; my %testhash; $testhash{ "Tier 1" } = { "Tier 2" => "Tier 3" }; my $ref = $testhash{ "Tier 1" }; print $testhash{ "Tier 1" }, " is a reference.\n"; ###### Works Great ######## print %$ref, " is dereferenced.\n"; ###### Dies Horribly ###### print %$testhash{ "Tier 1" }, " is dereferenced.\n";
Since $ref is the exact same hash reference as $testhash{ "Tier 1" }, why does Perl spit out "Global symbol "$testhash" requires explicit package name" when I try to dereference the latter? I'm guessing Perl thinks that $testhash is a non-existent scalar, but I can't figure out why it isn't returning as the hash reference value and derefencing it. And to prove they are the same ref:
print $ref, " is \$ref\n"; print $testhash{ "Tier 1" }, " is \$testhash\{ \"Tier 1\" \}\n"; ------------------------------ HASH(0x8dc2bdc) is $ref HASH(0x8dc2bdc) is $testhash{ "Tier 1" }
Thanks!

Replies are listed 'Best First'.
Re: Nested Hash Dereferencing Syntax
by ikegami (Patriarch) on Feb 24, 2009 at 17:27 UTC
    Perl sees %$testhash, but doesn't know of any $testhash. You want %{ $testhash{ "Tier 1" } }
      Nice. I tried parens, but not curlies, in my attempt to make sure Perl was evaluating the value of $testhash{ "Tier 1" } before trying to dereference.
      Do you know why curlies, and not parens, are necessary here? Just curious.
      Thanks for your help!
        Here is an explanation of why parens cannot be used there.

        If you could write %($hash{$key}) then you should expect to be able to write %($hash{$key}){$other_key}. But perlvar tells us that $( is a built-in special variable, so correctly knowing how to parse that would be very, very hard.

        Incidentally %( is a valid Perl hash, though it is not used for anything and accessing it can get tricky. But the following is valid Perl:

        %( = 0..9; print keys(%();
        Do you know why curlies, and not parens, are necessary here?

        Because parentheses only ever group things, never performing any nesting or scoping or accessing.

        No, I don't know why. Curlies are always used where are variables name is expected.
        my $x = ${$hash_ref}{key}; # Original syntax my $x = $hash_ref->{key}; # Newer, cleaner syntax print($foo, "bar\n"); print("${foo}bar\n"); # same print("$foobar\n"); # XXX my $x = ${"varname"}; # Symbolic reference

        etc.

        It strikes me that curlies (or braces) are used for legacy reasons given that the provenance of the language is the *NIX shell (see, to name but one, Perl).

        As we all know, *NIX shell uses braces in references to environment variables - when and only when the variable isn't followed by a printable, non-word boundary char can the braces be omitted e.g. ${foo}_bar is the var foo with _bar appended, whereas $foo_bar refers to a variable named foo_bar.

        This (string interpolation) is true for both shell and perl, but interestingly (I really ought to get out more:-) not in make(1) scripts - which can take braces or parens as separators.

        Update:

        Thanx to tilly for the hint.

        A user level that continues to overstate my experience :-))
Re: Nested Hash Dereferencing Syntax
by planetscape (Chancellor) on Feb 24, 2009 at 18:52 UTC

    You may also wish to read through the Tutorials in this category: References.

    HTH,

    planetscape
Re: Nested Hash Dereferencing Syntax
by toolic (Bishop) on Feb 24, 2009 at 17:36 UTC