Подтвердить что ты не робот

Элемент массива, автоматически установленный в undef, не будет меняться при сглаживании?

Относительно этого вопроса, какая разница между установленным вручную к элементу списка undef и тому, который был установлен Perl при увеличении размера этот список, назначая более крупный индекс, чем размер списка, при алиас? Например, учитывая этот код:

@a = (undef, 0);
@b = ();
$b[1] = 0;

print Dumper(@a), "\n", Dumper(@b);

Он печатает (как и ожидалось, я думаю):

$VAR1 = undef;
$VAR2 = 0;

$VAR1 = undef;
$VAR2 = 0;

Итак, не являются ли массивы одинаковыми? Видимо, не:

sub change { $_[0] = 1 }
change(@a); change(@b);
print Dumper(@a), "\n", Dumper(@b);

Какие принты:

$VAR1 = 1;
$VAR2 = 0;

$VAR1 = undef;
$VAR2 = 0;
4b9b3361

Ответ 1

Вы нашли захватывающий фрейм.

Когда вы явно устанавливаете элемент, он сначала возникает. Если массив расширен так, что несколько индексов попадают в диапазон этого массива, никакие скаляры неявно инициализируются на этих позициях. Пример:

my @array;
$array[2] = undef; # this extends the array
# now elements 0–2 report as `undef`, but only #2 was initalized

Когда мы спрашиваем, существуют ли эти элементы, мы получаем:

say "index $_ ", exists $array[$_] ? "exists" : "doesn't exist" for 0 .. 4;

Вывод:

index 0 doesn't exist
index 1 doesn't exist
index 2 exists
index 3 doesn't exist
index 4 doesn't exist

Эта оптимизация избавляет вас от выделения неиспользуемых скаляров на этих позициях; код доступа к массиву просто возвращает undef, если в противном случае ничего не говорится.

Теперь это квадраты плохо с вызовами функций. Когда вызывается подпрограмма, в стек помещается плоский список скаляров, который затем доступен как @_. Здесь нет копирования, так что это вызов псевдонимом. Теперь, когда элемент $_[0] обращается к вашему югу, здесь нет скаляра, поэтому он создает новый в @_:

sub crazy {
  say 1*exists $_[0];
  $_[0] = 1;
  say 1*exists $_[0];
}

my @array; $array[2] = 0;
crazy @array;

say 1*exists $array[0];

Вывод:

0
1
0

Внутренне скаляр является указателем на структуру SV. Эти указатели копируются в стек, поэтому это делает невозможным фактическое изменение оригинала @array.

Ответ 2

Одно отличие состоит в том, что exists $a[0] истинно, а exists $b[0] - false.