Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

exists on hash autovivifies right?

by Anonymous Monk
on Jun 28, 2008 at 23:01 UTC ( [id://694546]=perlquestion: print w/replies, xml ) Need Help??

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

haven't used perl for a while, recent doing some project in perl. Quick question... my impression is that exists on hash autovivifies the element, am I right? I use version 10, does it make any difference, hoping this behavior get fixed in newer versions, or at least in the furture. what's perl 6's supposed behavior?

Replies are listed 'Best First'.
Re: exists on hash autovivifies right?
by pc88mxer (Vicar) on Jun 28, 2008 at 23:07 UTC
    Yes, it will autovivify intermediate structures (tested with 5.8.8 and 5.10) but not the final element being tested:
    use Data::Dumper; my $x; if (exists $x->{a}->{c}) { print "c exists\n"; } else { print "c doesn't exists\n"; } print Dumper($x); __END__ c doesn't exist $VAR1 = { 'a' => {} };
    Update: added confirmation about 5.10

      No, not really. exists never autovivifies, but it doesn't prevent anything else (such as ->) from causing autovivification. In the given example ($x->{a}->{c}), the first -> autovivifies $x and the second -> autovivifies $x->{a}. This occurs independently of exists.

      >perl -le"$x->{a}->{c}; print $x; print $x->{a}" HASH(0x225f18) HASH(0x226020)
        this is the best answer I read so far. thanks.
      If you need to test for existence without autovivification, you'll have to code up a test that goes something like this:
      sub my_exists { my $struct = shift; while (@_) { my $key = shift(@_); return false unless exists $hash->{$key}; $hash = $hash->{$key}; } 1; } my $x = {}; if (my_exists($x, 'a', 'c')) { print "c exists\n"; } else { print "c doesn't exist\n"; } print Dumper($x);
        nice solution. thanks.
      cool!
        well, cool that you answered. btu I dislike the behavior a lot. who does not?
          A reply falls below the community's threshold of quality. You may see it by logging in.
Re: exists on hash autovivifies right?
by GrandFather (Saint) on Jun 28, 2008 at 23:17 UTC

    No. exists would always return true if it autovivified the element being tested. It will however autovivify any elements the element being tested depends on. Consider:

    use strict; use warnings; my %hash; if (exists $hash{top}{dependent}) { print "\$hash{top}{dependent} exists\n"; } else { print "\$hash{top}{dependent} does not exist\n"; } if (exists $hash{top}) { print "\$hash{top} exists\n"; } else { print "\$hash{top} does not exist\n"; }

    Prints:

    $hash{top}{dependent} does not exist $hash{top} exists

    Perl is environmentally friendly - it saves trees
      I noticed that from the first example, and my memory of auto-vivification did fade a little. you said "exists would always return true if it autovivified the element being tested", well not entirely true, depends on sequence of events, but that's meaningless argue any way. thanks for taking your time.

        If it tested first but autovivified anyway it'd have to be named 'existed' because having made the test you would know that it exists. ;)


        Perl is environmentally friendly - it saves trees
Re: exists on hash autovivifies right?
by ysth (Canon) on Jun 29, 2008 at 05:42 UTC
    You can protect against it with || (at the cost of some ugliness), like so:
    # instead of: if (exists $x->{a}[0]{c}) { if (exists ${ ${ $x->{a} || [] }[0] || {} }{c}) {
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: exists on hash autovivifies right?
by GrandFather (Saint) on Jun 28, 2008 at 23:59 UTC

    I don't know what the application domain is nor how you got bit by this behaviour, but you may find Data::Diver helps.


    Perl is environmentally friendly - it saves trees
      no, it didn't get me. I was aware of this from start on, so the code was right. just wanted to confirm my understanding, since I haven't perl 4 a while. played with given/when and say, nice little improvement.
Re: exists on hash autovivifies right?
by ysth (Canon) on Jun 29, 2008 at 21:50 UTC
      That will turn an attempt to autovivify into an exception.
      $ perl -MHash::Util=lock_keys -wle 'my %x; lock_keys %x; exists $x{a}{ +b}' Attempt to access disallowed key 'a' in a restricted hash at -e line 1 +.

      Very useful for debugging.

        that also turns lots of other things into an exception, good luck.
      that's not a solution, unless the lock on keys is what you happen to want. a solution must be precise.
Re: exists on hash autovivifies right?
by Anonymous Monk on Jun 28, 2008 at 23:02 UTC
    missed a small thing.. it vivifies to undef?
Re: exists on hash autovivifies right?
by menolly (Hermit) on Jun 30, 2008 at 21:18 UTC

    I've taken advantage of short-circuiting operators to deal with this in the past, like so:
    if (exists($x->{a}) && exists($x->{a}->{c}) { #do stuff }

    Might get annoying if your hash is particularly deep, though.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (None)
    As of 2024-04-25 02:05 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found