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 должен автоматически оживить одно звено в цепочке, чтобы он мог проверить наличие следующего.