APM: Interesting hash side effect

Mike South msouth at fulcrum.org
Thu Jan 9 15:31:36 CST 2003


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.


>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