APM: Interesting hash side effect
Mike South
msouth at fulcrum.org
Thu Jan 9 15:31:36 CST 2003
Brian,
looks like you're not the only one surprised by this:
[From the POD on the exists() function (type "perldoc -f exists" at your
command prompt):]
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 deepest 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:
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.
In one part of the perlref documentation, it seems to imply that
autovivification only happens in lvalue situtations, which is what
I think the author of the above text is referring to. In another
part it just says
References of the appropriate type can spring into existence if
you dereference them in a context that assumes they exist.
So, it looks like this is one of those, for now.
mike
>From: "Brian Michalk" <michalk at awpi.com>
>To: "Mark Lehmann" <mlehmann at marklehmann.com>,
> "Austin Perl Mongers" <austin-pm at pm.org>
>Subject: APM: Interesting hash side effect
>Date: Thu, 9 Jan 2003 12:45:41 -0600
>
>I have had a nagging bug that I finally figured out.
>I found that in some cases checking to see if a hash element is defined will
>add to the hash.
>The following line:
> 103 if (defined $self->{keys}{cfg}{$varname}{ref_sub}) {
>will add the hash element, $self->{keys}{cfg}{$varname}. I had to change my
>code to the following in order to get it to work correctly.
>
> 102 if (defined $self->{keys}{cfg}{$varname}) {
> 103 if (defined $self->{keys}{cfg}{$varname}{ref_sub}) {
> 104 return $self->{keys}{cfg}{$varname}{ref_sub};
> 105 }
> 106 } else {
> 107 return undef;
> 108 }
>
>I hope this helps anyone else who cares.
More information about the Austin
mailing list