John Doe
John Doe

Reputation: 1138

Perl auto-vivification on assignment

Does Perl real auto-vivifies key when the unexisting key is assigned to a variable?

I have this code :

my $variable = $self->{database}->{'my_key'}[0];

The variable $self->{database}->{'my_key'}[0] is undefined in my hash, but if I print a Dumper after the assignment, I'm surprised that the my_key is created.

I know the functionality for this case :

use Data::Dumper;

my $array;

$array->[3] = 'Buster';  # autovivification
print Dumper( $array );

This will give me the results :

$VAR1 = [ undef, undef, undef, 'Buster' ];

But never expected to work the other way arround, where : my $weird_autovivification = $array->[3]; will also vivify $array->[3].

Upvotes: 1

Views: 356

Answers (2)

ikegami
ikegami

Reputation: 386621

Does Perl real auto-vivifies key when the unexisting key is assigned to a variable?

Perl autovivifies variables (including array elements and hash values) when they are dereferenced.

$foo->{bar}   [ $foo dereferenced as a hash   ]    ≡    ( $foo //= {} )->{bar}
$foo->[3]     [ $foo dereferenced as an array ]    ≡    ( $foo //= [] )->[3]
$$foo         [ $foo dereferenced as a scalar ]    ≡    ${ $foo //= do { my \$anon } }
etc

This means that

$self->{database}->{'my_key'}[0]

autovivifies

  • $self (to a hash ref if undefined)
  • $self->{database} (to a hash ref if undefined)
  • $self->{database}->{'my_key'} (to an array ref if undefined)

but not

  • $self->{database}->{'my_key'}[0] (since it wasn't dereferenced)

But never expected to work the other way arround, where : my $weird_autovivification = $array->[3]; will also vivify $array->[3].

Not quite. It autovivifies $array, the variable being dereferenced. Nothing was assigned to $array->[3] since it wasn't dereferenced.


Tip: The autovivification pragma can be used to control when autovivification occurs.

Upvotes: 8

Dave Cross
Dave Cross

Reputation: 69314

But never expected to work the other way arround, where : my $weird_autovivification = $array->[3]; will also vivificate $array[3].

That's not how it works.

$ perl -MData::Dumper -E'$foo=$array->[3]; say Dumper $array'
$VAR1 = [];

Executing that code has turned $array into an array reference (where, previously, it would have been undefined), but it hasn't set $array->[3] to anything.

If we add another level of look-up, we get slightly different behaviour:

$ perl -MData::Dumper -E'$foo=$array->[0][3]; say Dumper $array'
$VAR1 = [
          []
        ];

Here, Perl has created $array->[0] and set it to a reference to an empty array, but it hasn't affected $array->[0][3].

In general, as you're going through a chain of look-ups in a complex data structure, Perl will autovivify all but the last link in the chain. When you think about it, that makes a lot of sense. Perl needs to autovivify one link in the chain so that it can check the existence of the next one.

Upvotes: 11

Related Questions