Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

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 }
---
$world=~s/war/peace/g


Comment on Re^7: Why does exists cause autovivication?
Select or Download Code
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.

      --shmem

      _($_=" "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?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://659951]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (15)
As of 2015-07-02 13:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (40 votes), past polls