Sunday, August 23, 2009

Autovivification - a reminder

Most of you already know this by heart, but the odd reader may have forgotten.

Autovivification is what we call the process of automatically creating entries in built-in data structures (Perl 5: array/list and hash), usually at the time we check whether an inner element exists or not.

This can be a royal PITA, if you don't pay attention to the problem. That's why it keeps being mentioned.

Here's a simple example:

my %hash;
my $n;
while (!exists ($hash{x}) && $n < 5) {
$n++;
if (!exists ($hash{x}{y}) {
print "hash{x}{y} does not exist: $n\n";
}
}

Q: How many times does the above while loop run in Perl 5?
A: Once.

The simple matter of checking the existence of the inner hash resulted in an entry being created for $hash{x}.

That means that tests like these should be written more carefully:


if (defined ($hash{x})) {
if (!exists ($hash{x}{y}) {
print "$n: hash{x}{y} does not exist.\n";
}
} else {
print "$n: hash{x} is undefined.\n";
}

This prints $n: hash{x} is undefined. (with an incrementing $n) five times.


Edit 2009-08-24 18:49 UTC: MST commented that there is an autovivification module on CPAN that lets us say no autovivification; - and it's even lexically scoped! That's just $notreallyanexpletive brilliant! Thanks, Matt, and thanks, Vincent!


Oh, BTW, Perl 6 has a useful specification for autovivification, which illuminates the problem further.

1 comment:

Matt said...

And of course you can use 'no autovivification' to turn it off once you've installed the autovivification CPAN module.

-- mst