Turn off autovivification when you don’t want it

Autovivification, although a great feature, might bite you when you don’t expect it. I explained this feature in Understand autovivification, but I didn’t tell you that there’s a way to control it and even turn it off completely.

The autovivification pragma, which you can get from CPAN, lets you decide how autovivification works, or doesn’t work. As you saw in Understand autovivification, there are several ways that autovivification comes into play, specifically when you dereference an undefined value to:

  • fetch a value
  • store a value
  • test an undefined value with exists
  • delete an element

The pragma lets you control each of these independently.

The simplest use is simply unimport the module with no. This gets a bit tricky because this pragma is more interesting for what you disallow rather than enable:

no autovivification;

With no arguments, this turns off autovivification for fetching a value, or using delete or exists. This does not turn off autovivification for storing a value. You’re more likely to make mistakes with those first three, and most likely to get what you want with the last one.

None of these work, in that they don’t create any more of the data structure:

no autovivification;

my $cats;
delete $cats{'Buster'};
my $foo = $cats{'Buster'}; 

if( exists $cats{'Buster'} ) { 1 }

use Data::Dumper;
print Dumper( $cats );

You don’t get an error or a warning, but nothing happens to $cats, which is still undefined at the end. The pragma just leaves the undefined value as it is and your program continues. In those cases, you still get the answers that expect. When the element isn’t there, you still get undef when you try to access it. It stills returns false when you try exists and the element isn’t there after a exists. Your program continues without a warning.

If you want to know when you’ve skipped at possible autovivification, you can also tell autovivification to warn you, or if you’re really paranoid, kill your program.

Including the warn option gives you warnings. As with any import list, when you specify something you override all defaults. If you still want those defaults, you have to list them explicitly:

no autovivification qw(fetch delete exists warn);

use Data::Dumper;

my $cats;

delete $cats->{Buster};

print Dumper( $cats );

Now you get a warning:

Reference was vivified at auto.pl line 7.
$VAR1 = undef;

If you want to stop the program, you use strict instead of warn:

no autovivification qw(fetch delete exists strict);

use Data::Dumper;

my $cats;

delete $cats->{Buster};

print Dumper( $cats );

Your program stops at the point that Perl tries to autovivify something and gives you an file and line where autovivification stopped your program:

Reference vivification forbidden at auto.pl line 7.

When you store a value, however, autovivification doesn’t get in your way, even if you create a deep one:

no autovivification;

use Data::Dumper;

my $cats;

$cats->{Buster}{count} = 9;

print Dumper( $cats );

You still autovivified the structure:

$VAR1 = {
          'Buster' => {
                        'count' => 9
                      }
        };

If you want to turn off autovification for storing a variable, you have to explicitly disallow it. As before, you have to provide the other default options that you’d like to keep:

no autovivification qw(fetch delete exists store strict);

use Data::Dumper;

my $cats;

$cats->{Buster}++;

print Dumper( $cats );

Now, when you try to autovivify a hash reference to store a value in the Buster key, your program stops (because you are also using strict:

Reference vivification forbidden at auto.pl line 7.

Lexical scope

You can limit the effect of autovivification pragma to part of your program by using it in only in the scope where you need it. There are two ways that you can do this, depending on what you need.

First, you can turn off all autovivification for the entire file (which is itself a scope, see Know what creates a scope), but re-enable it for the bits where you need it:

no autovivification qw(fetch delete exists store strict);

# can't do it in here

{
use autovivification qw(store);

...; # allow some of it in here
}

# can't do it in here, either

Second, you can leave Perl’s normal autovivification features in place for the entire file, but turn it off in the sensitive parts of the program, just as in Item 100. Use lexical warnings to selectively turn on or off complaints (but in this case, engaging safety features):

...; # program with possible autovivification

{
# can't do it in here
no autovivification qw(fetch delete exists store strict);

}

...; # program with possible autovivification

Things to remember

  • The autovivification pragma lets you disable Perl’s automatic data structure creation
  • The defaults do not prevent you from assigning to an autovivified reference
  • You can enable warnings or errors to catch autovivification events
Leave a comment

0 Comments.

Leave a Reply


[ Ctrl + Enter ]