For the first time in more than five years, I got bit by autovivification. It’s one of those odd quirks of Perl that I’d read about, and heard the problems with but never bumped in to them.
I had put together a chunk of code using a hashref, which differentiated between the hash being undefined and being empty.
My hashref was initialized:
my $hashref = undef;
Code read:
return if exists $hashref->{something};
load_hashref($hashref) unless defined $hashref
See how that isn’t going to work? I see it now, but it took a few miutes of dinking around with Data::Dumper to figure out what was happening.
The use of $hashref->{something} autovivifies the hash in $hashref to {}, which messes up the undef check below it.
Now I have to decide if I’m going to change the code to check if the hash is empty rather than undef, or if I’m going to stick a “defined $hashref and” before the exists check and short-circuit the exists and autovivification.
Using {} will be more robust, so I should go that way.
How do you tell if a hash is empty, anyway? keys gives a list, and the list in scalar context is the number of items.
Code is now:
my $hashref = {};
return if exists $hashref->{something};load_hashref($hashref) unless scalar keys %$hashref;
Thus, nothing will come along and screw up the code by accidentally referring to the hash.
Yay!
Tags: Perl
The last line can even be simpler:
load_hashref($hashref) unless %$hashref;
Best regards,
you shouldn’t need scalar keys
my $hashref = {};
return if exists $hashref->{something};
load_hashref($hashref) unless %$hashref;
I was following the advice from http://www.perlmonks.org/?node_id=173677 which points out that not all tied hashes behave properly in those situations.
In my specific case, it would have been fine, but in the general case it might not always work.
you don’t need to use scalar keys, just using a hash in scalar context would work as well
I like
return if $hashref and exists $hashref->{something};
much better than counting the keys.