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 }
In reply to Re^7: Why does exists cause autovivication?
by demerphq
in thread Why does exists cause autovivication?
by Argel
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |