Perl авто-вивификация по заданию

Действительно ли Perl автоматически оживляет ключ, когда несуществующий ключ назначается переменной?

У меня есть этот код:

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

Переменная $self->{database}->{'my_key'}[0] не определено в моем хэше, но если я распечатаю Dumper после назначения, я удивляюсь, что my_key создано.

Я знаю функциональность для этого случая:

use Data::Dumper;

my $array;

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

Это даст мне результаты:

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

Но никогда не ожидалось, что он будет работать иначе, где: my $weird_autovivification = $array->[3]; также оживит $array->[3],

2 ответа

Решение

Действительно ли Perl автоматически оживляет ключ, когда несуществующий ключ назначается переменной?

Perl автоматически оживляет переменные (включая элементы массива и значения хеша) при разыменовании.

$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

Это означает, что

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

autovivifies

  • $self (в хеш-ссылку, если она не определена)
  • $self->{database} (в хеш-ссылку, если она не определена)
  • $self->{database}->{'my_key'} (в массив ref, если он не определен)

но нет

  • $self->{database}->{'my_key'}[0] (так как он не был разыменован)

Но никогда не ожидалось, что он будет работать иначе, где: my $weird_autovivification = $array->[3]; также оживит $array->[3] ,

Не совсем. Это автовивизирует $array переменная разыменовывается. Ничего не было назначено $array->[3] так как он не был разыменован.


Совет: Прагма автовивификации может использоваться для контроля, когда происходит автовивификация.

Но никогда не ожидалось, что он будет работать иначе, где: my $weird_autovivification = $array->[3]; также оживит $array[3],

Это не так, как это работает.

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

Выполнение этого кода оказалось $array в ссылку на массив (где ранее он был бы неопределен), но он не установил $array->[3] ни к чему.

Если мы добавим еще один уровень поиска, мы получим немного другое поведение:

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

Здесь Perl создал $array->[0] и установите для него ссылку на пустой массив, но это не повлияло $array->[0][3],

В целом, когда вы просматриваете цепочку поисков в сложной структуре данных, Perl будет автоматически активировать все, кроме последнего звена в цепочке. Когда вы думаете об этом, это имеет большой смысл. Perl должен автоматически оживить одно звено в цепочке, чтобы он мог проверить наличие следующего.

Другие вопросы по тегам