Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Populating a nested hash with itself?

by jkva (Chaplain)
on Jul 06, 2005 at 14:44 UTC ( [id://472824]=perlquestion: print w/replies, xml ) Need Help??

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

Update : Fixed a significant amount of typos.

Update : Apologies for the dupe.

Fellow Monestacrustacians (Thanks Transient ;) ),

At the moment I am trying to accomplish the following : I have a nested hash, like this :

my %hash = (); my $hashref = \%hash; %hash = ( key1 => { key1_1 => ["value1_1",value1_2"], key1_2 => "w00t!", }, key2 => { key2_1 => "wakkawak!", key2_2 => $hashref->{key1}{key1_1}, }, );

But $hash{key2}{key2_1} will return undef.
Perhaps I am doing something very foolish, I don't know, therefore I ask here. Any help is appreciated.

Your fellow Monk, Detonite.

Replies are listed 'Best First'.
Re: Populating a nested hash with itself?
by ikegami (Patriarch) on Jul 06, 2005 at 14:50 UTC

    It doesn't work because there isn't anything in %hash (or %$hashref) at the time $hashref->{key1}{key1_1} is evaluated. The assignent of the list to %hash (and therefore to %$hashref) only happens when the ")" is reached. The following would work:

    my %hash; my $hashref = \%hash; $hash{key1} = { key1_1 = ["value1_1",value1_2"], key1_2 = "w00t!", }; $hash{key2} = { key2_1 = "wakkawak!", key2_2 = $hashref->{key1}{key1_1}, };

    so would:

    my $it = ["value1_1",value1_2"]; my %hash = ( key1 => { key1_1 = $it, key1_2 = "w00t!", }, key2 => { key2_1 = "wakkawak!", key2_2 = $it, }, ); my $hashref = \%hash;
Re: Populating a nested hash with itself?
by bart (Canon) on Jul 06, 2005 at 14:48 UTC
    Replace = with => in your inner hashes.

    And you can't read the value of one inner hash before it is set. You have to assign to it in steps.

    %hash = ( key1 => { key1_1 => ["value1_1",value1_2"], key1_2 => "w00t!", }, key2 => { key2_1 => "wakkawak!", # key2_2 => $hashref->{key1}{key1_1}, # postpon +e, can't read it yet... }, ); $hash{key2}{key2_2} = $hashref->{key1}{key1_1}; # now you can.
Re: Populating a nested hash with itself?
by Joost (Canon) on Jul 06, 2005 at 14:53 UTC
    Eehmm.. It's usually best to copy & paste actual running code :-)
    #!/usr/bin/perl -w use strict; use Data::Dumper; my %hash = (); my $hashref = \%hash; %hash = ( key1 => { key1_1 => ["value1_1","value1_2"], key1_2 => "w00t!", }, key2 => { key2_1 => "wakkawak!", key2_2 => $hashref->{key1}, # update! }, ); print Dumper($hashref);

    I think the problem is that the whole %hash = ( ... ) thing is a single statement, and the actual assignment would be done after all the rest of the statement is resolved, (so after $hashref->{key2}{key1_1} is resolved).

    You need to split this up in two statements:

    #!/usr/bin/perl -w use strict; use Data::Dumper; my %hash = (); my $hashref = \%hash; %hash = ( key1 => { key1_1 => ["value1_1","value1_2"], key1_2 => "w00t!", }, key2 => { key2_1 => "wakkawak!", }, ); $hash{key2}{key2_2} = $hashref->{key1}; #update! print Dumper($hashref);
    updated: $hashref->{key1_1} is always undef, ofcourse.

Re: Populating a nested hash with itself?
by PhilHibbs (Hermit) on Jul 06, 2005 at 14:52 UTC
    It seems to me that this code is building an arraya list, and then loading it into a hash. While building the arraylist, $hashref points to an empty hash.

    I'm a little unsure what order things happen in behind the scenes, maybe hash assignment is done one entry at a time, so the first entry is created and added to the target variable so that the second entry can refer to it, but I doubt it.

      I'm a little unsure what order things happen in behind the scenes, maybe hash assignment is done one entry at a time

      Parens have higher precedence than the assignment operator, so the list (nit: it's a "list", not an "array") is contructed before the assignment is performed. This isn't a hash constructor. There isn't such a thing in Perl. The code creates a list, which is then assigned to the hash.

        Yes, that's what my inner C programmer told me, but I don't trust Perl not to do some crazy magic (DWIMer?)
Re: Populating a nested hash with itself?
by halley (Prior) on Jul 06, 2005 at 14:55 UTC
    I could swear I saw this exact question a few days ago.

    Short version: The contents you're assigning aren't in the hash until after the assignment %hash = ( ... ) is done. Thus, you'll have to build it up in steps if you want to build some hash keys relative to the assigned hash.

    --
    [ e d @ h a l l e y . c c ]

Re: Populating a nested hash with itself?
by Tanktalus (Canon) on Jul 06, 2005 at 16:45 UTC

    I did notice that Data::Dumper does nearly the same thing you're trying to do ... and I'm trying to figure out how to get Data::Dumper's output to "thaw" back into a usable perl variable. Perhaps someone else will answer this.

    my $a = [qw{v1 v2}]; my %h = ( k1 => { k11 => $a, k12 => 'w00t!', }, k2 => { k21 => 'what?', k22 => $a, }, ); use Data::Dumper; #print Dumper(\%h); my $h2; $h2 = { 'k2' => { 'k21' => 'what?', 'k22' => [ 'v1', 'v2' ] }, 'k1' => { 'k11' => $h2->{'k2'}{'k22'}, 'k12' => 'w00t!' } }; print Dumper($h2);
    The first hash, %h, is what you're trying to do, but in a manner that works. Then I dump it, and I pasted that output back into the code and dump the new hash-ref, $h2. But it doesn't want to work, and I'm not sure what bits of trickery are needed to get it to work - probably some Data::Dumper variables when dumping, but I'm not sure offhand.

      The output of Data::Dumper is not guaranteed to properly evaluate and reconstruct the data, unless you set $Data::Dumper::Purity = 1. It is still possible to confuse Data::Dumper in some cases, but with Purity, it'll handle most self-referential and other cyclical structures. The output with this configuration:
      $VAR1 = { 'k1' => { 'k11' => [ 'v1', 'v2' ], 'k12' => 'w00t!' }, 'k2' => { 'k21' => 'what?', 'k22' => [] } }; $VAR1->{'k2'}{'k22'} = $VAR1->{'k1'}{'k11'};
      As you can see, Data::Dumper now produces Perl code, and not merely a Perl-like syntax to describe the data.

      --
      [ e d @ h a l l e y . c c ]

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://472824]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-04-16 09:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found