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

I'm trying to create a hash that is named using the data from a scalar.
use strict; use warnings; my $foo = "bar"; my %$foo=("key1"=>"value1","key2"=>"value2"); print $bar{"key1"};
I thought that Perl would substitute "bar" into %$foo to make it %bar, but apparently it does not. I get the errors:
"my" variable $foo masks earlier declaration in same scope at test.pl line 6.
Can't declare hash dereference in my at test.pl line 6, near "$foo="
Global symbol "%bar" requires explicit package name at test.pl line 7.
Execution of test.pl aborted due to compilation errors.
Suggestions? Thanks.

Replies are listed 'Best First'.
Re: Hash references?
by FunkyMonk (Bishop) on May 02, 2008 at 18:50 UTC
    Use a hash of hashes instead:
    my %hoh; my $foo = "bar"; $hoh{$foo} = { "key1"=>"value1","key2"=>"value2" }; print $hoh{$foo}{"key1"}; print $hoh{bar}{"key1"}; # same thing


    Unless I state otherwise, all my code runs with strict and warnings
Re: Hash references?
by pc88mxer (Vicar) on May 02, 2008 at 18:49 UTC
    my %$foo=("key1"=>"value1","key2"=>"value2");
    I think you really want:
    my %foo=("key1"=>...);
    The difference is that $foo refers to the scalar variable whereas $foo{'key1'} accesses the hash %foo (with key key1).

    If you want to create a reference to a hash, use curly braces:

    my $hash_ref = { key1 => ... };
    and then you access values in the hash with the -> operator, e.g. $hash_ref->{key1}.
Re: Hash references?
by ikegami (Patriarch) on May 02, 2008 at 22:19 UTC

    Two problems.

    The first problem is the second my. The argument of my needs to be a variable name (not an expression such as %$foo) or a parenthesized list of variable names. Remove the my, and package variable %bar will be populated.

    Well, not quite. By using use strict;, you're explicitly telling Perl to disallow you from doing what you want to do. And rightfully so. What you want to do is highly discouraged: Why it's stupid to 'use a variable as a variable name'. Using a Hash of Hash (HoH) would be a better approach. See FunkyMonk's reply to see how that's done.

      Because of the way the actual script is structured, I already had a hash of hashes, and I was trying to avoid creating a hash of hashes of hashes (HoHoH?) by creating the HoHs with soft references. However, after reading "Why it's stupid to 'use a variable as a variable name' ", I now realize that it's really just easier to deal with the three dimensional hash. Thanks again for the Perl Wisdom.
Re: Hash references?
by linuxer (Curate) on May 02, 2008 at 21:18 UTC

    It looks like you tried to create a symbolic reference.

    Usually you don't want to do this, because it can bring you more trouble than you'll expect.

    If you're not sure about what you want to do, use a hash of hashes instead; which has already been mentioned before.

    And using "strict" helps you to avoid this type of reference...(which is usually a good thing)