in reply to perl: restrict perl from automaticaly creating a hash branches on check

This is cross posted on The Perl Guru forum (http://perlguru.com/gforum.cgi?post=80149;sb=post_latest_reply;so=ASC;forum_view=forum_view_collapsed;;page=unread#unread) and apparently also on SO. It is considered polite to inform the reader about cross-posts to avoid duplicate work at various places of the Internet.

I have provided two answers on the Perl Guru. Just to repeat here: the autovivification module or the hard manual way, quickly demonstrated here under the Perl debugger:

DB<1> $h{a}{b}{c} = 2; DB<2> print "foo" if defined $h{d}{e}{f} ; DB<3> print "foo" if $h{g} && $h{g}{h} && $h{g}{h}{i}; DB<4> x \%h; 0 HASH(0x600500b60) 'a' => HASH(0x600509d30) 'b' => HASH(0x600500a88) 'c' => 2 'd' => HASH(0x600500c38) 'e' => HASH(0x600500980) empty hash DB<5>
Line 1 (DB<1>) is just creating the hash, to make sure it exists.

Line 2 is checking for the definedness of a deeply nested element of the hash.

Line 3 is doing the same thing, but level by level. If the first conditional expression is false, the others will not be evaluated because they are short-circuited (the whole expression cannot be right if the first one is wrong (undefined).

Line 4 prints out the structure of the hash. You can see that line 2 created all the level below the last one (autovivification of levels 1 and 2), where as line 3 did not produce any autovivification (did not create subentries for the lower levels).

Update: corrected the case of the initial letter of the autovification module, which is lc, no uc as I originally wrote. Thanks to AnomalousMonk for the correction and for providing a link.

In addition, please note that the tests described in the debugger session above are really a quick example and that they might fail if the value in the most deeply nested value may be an end value rather than a reference to another sub-hash, in which case the test might return false despite the value being defined, if that value is itself false (for example 0 or the empty string). So that, depending on what the exact purpose of the test really is, it might sometimes be better or more reliable to rewrite line DB<3> above as:

print "foo" if $h{g} && $h{g}{h} && exists $h{g}{h}{i};
or possibly:
print "foo" if $h{g} && $h{g}{h} && defined $h{g}{h}{i};
The best solution between the three solutions really depends on what exactly you are trying to know and what the data structure really is (if you are guaranteed that the third nesting level cannot be an end value, but can only be a reference or not exist, then you don't need to worry about that, as a defined reference is always going to evaluate to true). All this to say that this was just an example, you'll need to adapt the syntax to the real scenario.

Also corrected a silly mistake in the initial DB<3> line.

Replies are listed 'Best First'.
Re^2: perl: restrict perl from automaticaly creating a hash branches on check
by AnomalousMonk (Archbishop) on Nov 06, 2014 at 19:39 UTC
Re^2: perl: restrict perl from automaticaly creating a hash branches on check
by alex5161 (Novice) on Nov 06, 2014 at 19:32 UTC

    You right, I did cross-posted: did not know wich forum has any activities.

    Will responce on that, perlguru forum

      The general consensus is that there is nothing wrong with cross-posting, but please just inform the readers on the various forums where you do that to prevent that people spend time trying to find a solution to something thazt has already been solved on the other end of the Internet.
Re^2: perl: restrict perl from automaticaly creating a hash branches on check
by Anonymous Monk on Nov 07, 2014 at 14:08 UTC

    Thanks for answers and corrections.

    I am responding to this and other posts on Perl-Guru-Forum: The same topic