Autovivification bit me today

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:

5 Responses to “Autovivification bit me today”

  1. Pedro Melo says:

    The last line can even be simpler:

    load_hashref($hashref) unless %$hashref;

    Best regards,

  2. matt says:

    you shouldn’t need scalar keys
    my $hashref = {};
    return if exists $hashref->{something};
    load_hashref($hashref) unless %$hashref;

  3. Laufeyjarson says:

    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.

  4. lwsitu says:

    you don’t need to use scalar keys, just using a hash in scalar context would work as well

  5. b says:

    I like

    return if $hashref and exists $hashref->{something};

    much better than counting the keys.

Leave a Reply