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;
| [reply] [d/l] [select] |
Re: Populating a nested hash with itself?
by bart (Canon) on Jul 06, 2005 at 14:48 UTC
|
%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.
| [reply] [d/l] |
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.
| [reply] [d/l] [select] |
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. | [reply] |
|
|
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.
| [reply] |
|
|
Yes, that's what my inner C programmer told me, but I don't trust Perl not to do some crazy magic (DWIMer?)
| [reply] |
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 ]
| [reply] [d/l] |
|
|
| [reply] |
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. | [reply] [d/l] |
|
|
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 ]
| [reply] [d/l] [select] |