Скалярное значение - это просто контейнер. Вы можете думать о них как об интеллектуальном указателе, а не как о примитивном значении.
Если вы выполняете присваивание
$foo = "something"; #or
$bar++;
, вы меняете значение скаляров, контейнер остается прежним,
Рассмотрим
my @b;
my $i=0;
for 1..5 -> $x {
$i++;
@b.push(($i<>,1)); # decontainerize $i and use the bare value
}
say @b;
и
my @b;
my $i=0;
for 1..5 -> $x {
$i := $i + 1; # replaces the container with value / change value
@b.push(($i,1));
}
say @b;
Оба из них работают как положено. Но: в обоих случаях, вещь в списке больше не является изменяемой, потому что нет контейнера.
@b[4;0] = 99;
поэтому умрет. Так что просто используйте переменную цикла, верно?
Нет.
for 1..5 -> $x {
@b.push(($x,1)); #
}
@b[4;0] = 99; #dies
, даже если мы перебираем список изменяемых объектов.
my $one = 1;
my $two = 2;
my $three = 3;
my $four = 4;
my $five = 5;
for ($one, $two, $three, $four, $five) -> $x {
@b.push(($x,1));
}
@b[4;0] = 99; #dies
Таким образом, здесь нет псевдонимов, вместо этого переменная циклавсегда один и тот же контейнер и получает присвоенные значения, которые поступают из других контейнеров.
Мы можем сделать это, хотя.
for ($one, $two, $three, $four, $five) <-> $x {
@b.push(($x,1));
}
@b[4;0] = 99; # works
for ($one, $two, $three, $four, $five) -> $x is rw {
@b.push(($x,1));
}
@b[4;0] = 99; # works too
Способ сделать изменяемым "вещь" является использование промежуточной переменной.
for 1..5 -> $x {
my $j = $x;
@b.push(($j,1)); # a new container
}
@b[4;0] = 99;
работает нормально. Или короче и больше в исходном контексте
my @b;
my $i=0;
for 1..5 -> $x {
$i++;
@b.push((my $ = $i, 1)); # a new anonymous container
}
@b[4;0] = 99;
say @b; # [(1 1) (2 1) (3 1) (4 1) (99 1)]
См. Также:
https://perl6advent.wordpress.com/2017/12/02/#theoneandonly https://docs.perl6.org/language/containers