Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Why does perl expression in empty nested hash create parents

by Steve_BZ (Chaplain)
on Feb 21, 2011 at 18:47 UTC ( #889462=perlquestion: print w/replies, xml ) Need Help??
Steve_BZ has asked for the wisdom of the Perl Monks concerning the following question:

Hi Guys,

Why does a Perl expression acting on an empty nested hash element create parents for the element eg:

#!/usr/bin/perl -w use strict; use warnings; my %a; my $a = scalar keys %{a}; print $a,"\n"; if (not exists $a{a}{a}{a}){ $a = scalar keys %{a}; print $a,"\n"; } print "End\n";

prints:

0 1 End

not

0 0 End

And is the only way to avoid this, to check the higher levels of the hash first?

Regards

Steve

Replies are listed 'Best First'.
Re: Why does perl expression in empty nested hash create parents
by Eliya (Vicar) on Feb 21, 2011 at 19:19 UTC
Re: Why does perl expression in empty nested hash create parents
by bellaire (Hermit) on Feb 21, 2011 at 19:21 UTC
    This was previously discussed here. This is known as autovivification, and is documented in the documentation for exists, and in perlref. Yes, the only way to avoid this behavior of exists is to check the higher levels of the hash first.
Re: Why does perl expression in empty nested hash create parents
by ikegami (Pope) on Feb 21, 2011 at 19:25 UTC
    $a{a}{a}{a}
    is short for
    $a{a}->{a}->{a}

    When the operand of a dereference (e.g. LHS of "->") is undef, it gets vivified into the right kind of reference. That means the above is short for

    ( ( $a{a} //= {} )->{a} //= {} )->{a}

    Solution? "no autovivification;"

Re: Why does perl expression in empty nested hash create parents
by furry_marmot (Pilgrim) on Feb 21, 2011 at 19:23 UTC
    Sadly, it's a feature, but it's the intermediate keys you are creating. Try this:
    print "1st run\n" if exists $a{a}; print "2nd run\n" if exists $a{a}{b}{c}; print "3rd run\n" if exists $a{a}; # prints 3rd run
    $a{a}{b} is created in order to test the existence of $a{a}{b}{c}. From perldoc -f exists:
    Note that the EXPR can be arbitrarily complicated as long as the final operation is a hash or array key lookup or subroutine name: if (exists $ref->{A}->{B}->{$key}) { } if (exists $hash{A}{B}{$key}) { } if (exists $ref->{A}->{B}->[$ix]) { } if (exists $hash{A}{B}[$ix]) { } if (exists &{$ref->{A}{B}{$key}}) { } Although the mostly deeply nested array or hash will not spring into existence just because its existence was tested, any intervening ones will. Thus "$ref->{"A"}" and "$ref->{"A"}->{"B"}" will spring into existence due to the existence test for the $key element above. This happens anywhere the arrow operator is used, including even here: undef $ref; if (exists $ref->{"Some key"}) { } print $ref; # prints HASH(0x80d3d5c) This surprising autovivification in what does not at first--or even second--glance appear to be an lvalue context may be fixed in a future release.
    But you can be smart about this. You can test for $a{a}. If it doesn't exist, any and all subkeys certainly won't exist.

    --marmot

Re: Why does perl expression in empty nested hash create parents
by Steve_BZ (Chaplain) on Feb 21, 2011 at 19:28 UTC

    Guys, thanks for your very quick responses. ++ all round! I felt that this was a difficult question to post, as some of the links suggested, without knowing the word 'autovivication' :)

    Regards

    Steve

      autovivification
Re: Why does perl expression in empty nested hash create parents
by mellon85 (Monk) on Feb 21, 2011 at 19:18 UTC
    If you search in the previous nodes this was already discussed. You need to check for each level as perl polulates the hashtable as you look into it
Re: Why does perl expression in empty nested hash create parents
by sundialsvc4 (Abbot) on Feb 22, 2011 at 15:29 UTC

    I think it was done this way because the present behavior is usually much more desirable in actual practice, most of the time.   If you want to create some arbitrarily-deep structure leading up to some piece of data that you want to store, bang! you can “just do it.”

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://889462]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2018-06-21 16:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?



    Results (118 votes). Check out past polls.

    Notices?