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

In one of my scripts it would be very convenient to create and name hashes dynamically. I can go around this with creating hash of hashes, but if i'd like to stick with only one hash and it's key/values, how should i do this?

In the code below i'm trying to illustrate the idea.

my @hashNames = qw(testA testB testC); my $i = 0; foreach (@hashNames) { %{$_}{'key'} = $i; }

I'm trying to create a hashes like below with the example above

%testA = ( key => '0' );

Replies are listed 'Best First'.
Re: Dynamically naming and creating hashes
by jdporter (Paladin) on Apr 11, 2006 at 16:09 UTC

    What you're talking about is called "symbolic references", and there's lots of literature explaining why it's generally a bad idea.

    In your case, I would recommend the following alternative:

    my( %testA, %testB, %testC ); my @hashrefs = \( %testA, %testB, %testC ); my $i = 0; foreach ( @hashrefs ) { $_->{'key'} = $i; }

    In other words, you create the hashes with the names you want, as normal.
    Then, whenever you need to iterate over all of them (which seems to be your motivation here), you iterate over a list of references to the hashes.
    In the example above, I created an array to hold the list of hash references, in case you need the list multiple times. If you only need it once, you could foreach over the list of hash refs directly.

    We're building the house of the future together.
Re: Dynamically naming and creating hashes
by xdg (Monsignor) on Apr 11, 2006 at 18:19 UTC
    i'd like to stick with only one hash and it's key/values

    Can you explain what's important about that to you? I'm surprised that you don't find the hash of hashes to be an easier and more versatile approach. Unlike the array of hashes or even array of names, a hash of hashes lets you use either the values or the keys, depending on whether you want to work with the hashes directly or with the names:

    my %hashes = map { $_ => {} } qw( testA testB testC ); # by hash my $i=0; $_->{'key'} = $i++ for values %hashes; # by name $hashes{$_}{'name'} = $_ for keys %hashes;

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Dynamically naming and creating hashes
by tinita (Parson) on Apr 11, 2006 at 18:19 UTC
    a hash is a mapping from a string to a scalar. the symbol table is (simplified) a mapping from a string (the variable name) to the variable.

    what you want to do is possible, but why bother with doing complicated things with the symbol table and even do no strict; when you can have a simple hash of hashes?

    my @hashNames = qw(testA testB testC); my $i = 0; my %hoh; foreach (@hashNames) { $hoh{$_}->{key} = $i; } # later print $hoh{testA}->{key};

    see perldata, perllol
Re: Dynamically naming and creating hashes
by codeacrobat (Chaplain) on Apr 11, 2006 at 16:59 UTC
    A fancy way to initialize %foo = (key => 0) and %bar = (key => 0).
    $$_{key} = 0 for qw(foo bar);
    Again, symbolic references are dangerous. Try to avoid them.
Re: Dynamically naming and creating hashes
by Anonymous Monk on Apr 11, 2006 at 16:30 UTC
    When indexing a hash, use $, not %.
    foreach (@hashNames) { ${$_}{'key'} = $i; }
    The above code is not equivalent to your example. The code below is.
    foreach (@hashNames) { %{$_} = ( key' => '0' ); }