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

Re^7: Why does exists cause autovivication?

by demerphq (Chancellor)
on Jan 02, 2008 at 11:01 UTC ( #659951=note: print w/replies, xml ) Need Help??

in reply to Re^6: Why does exists cause autovivication?
in thread Why does exists cause autovivication?

Exists checks to see that the lookup of $var->{$key} is successful, meaning that $key has been used to store a value in the hash prior to the check. Thus we have:

# $user_by_uid{$uid}->{$host} $var= $user_by_uid{$uid} $key= $host

What this means is that if the result of $user_by_uid{$uid} is undef (either by having an explicit undef value or by not being in the %user_by_uid hash at all) then it is autovivified. If there is a hash reference stored in $user_by_uid{$uid} (either intentionally or via autoviv) then the it is checked to see if $host had ever been used as a key.

Tring to reduce this to a one liner: exists checks the the last hash lookup you feed it, not if the full "path" through the data structure exists. This is more obvious if you consider $user_by_id[$uid]->{$host}, obviously exists doesnt operate on arrays, and we get no error, so it means that only ->{$host} part is relevent to exists.

You could always write a simple routine:

sub my_exists { my ($hash_ref,$key)= @_; return $hash_ref and exists $hash_ref->{$key} }

which would not autovivify. Compare it to how the real thing *might* be coded. Im pretty sure this actually wont work due to some subtleties of hash lookups and lvalue arguments but its pretty close to the real thing.

sub my_fake_exists { my ($hash_ref,$key)=@_; $hash_ref={} if not defined $hash_ref; #fake autoviv return exists $hash_ref->{$key}; # do the lookup }

Replies are listed 'Best First'.
Re^8: Why does exists cause autovivication?
by Argel (Prior) on Jan 02, 2008 at 20:45 UTC
    Okay, so is my original example:
    next unless exists $user_by_uid{$uid}->{$host};

    more like the following:

    $href = defined $user_by_uid{$uid} ? $user_by_uid{$uid} : {}; #Fake au +toviv next unless exists $href->{$host};

    Or would it be more like the following, using your example code?

    next unless my_fake_exists $user_by_uid{$uid}, $host;

    In other words, since there is no short-circuit evaluation to avoid the -> in my original example does that mean the autoviv occurs before anything is passed in to 'exists'?

    Thanks very much for taking time to respond and hope you had a Happy New Year!!

      No need to autovivify anything, only to test an empty hashref for a non-existent key.
      next unless exists $user_by_uid{$uid}; next unless exists $user_by_uid{$uid}->{$host};

      should do.


      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://659951]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2017-06-24 19:05 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (562 votes). Check out past polls.