Slip — это список значений, который может совмещаться во внешнюю последовательность.
Таким образом, следующее создает сглаженный список.
1, |(2, 3)
Это происходит из-за запятой ,
.
Если вы вставляете этот список в массив в заданной позиции, вы вставляете этот список в массив в одну заданную позицию.
@a[0] = 1, |(2, 3); # [(1,2,3),]
То же самое произойдет, если вы вставите Slip, поскольку Slip — это просто подкласс List.
@a[0] = |(2, 3); # [slip(2,3),]
На самом деле Slip — это почти исключительно список. Вот код от Rakudo для Slip.
# A Slip is a kind of List that is immediately incorporated into an iteration
# or another List. Other than that, it's a totally normal List.
my class Slip { # is List
# XXX this makes an empty Slip undefined?
multi method defined (Slip:D: --> Bool:D) { self.Bool }
multi method Slip(Slip:D:) { self }
method CALL-ME (+args) { args.Slip }
multi method raku(Slip:D: --> Str:D) {
nqp::if(
nqp::eqaddr(self,Empty),
'Empty',
nqp::stmts(
(my str $guts = callsame),
nqp::if(
nqp::eqat($guts,'$',0), # we're itemized
nqp::concat('$(slip',nqp::concat(nqp::substr($guts,1),')')),
nqp::concat('slip',$guts)
)
)
)
}
multi method List(Slip:D: --> List:D) {
my $list := nqp::create(List);
nqp::bindattr($list,List,'$!todo',nqp::getattr(self,List,'$!todo'))
if nqp::isconcrete(nqp::getattr(self,List,'$!todo'));
nqp::bindattr($list,List,'$!reified',nqp::getattr(self,List,'$!reified'))
if nqp::isconcrete(nqp::getattr(self,List,'$!reified'));
$list
}
}
Это заставляет работать только 4 функции.
|().defined
Это определено?
Если он содержит элементы, да, иначе нет.
(Empty
определенно не определено, но |(,)
или slip()
, возможно, должны быть определены. Этот метод просто говорит, что оба не определены.)
Slip((1,2))
Превратите существующий список в бланк.
Empty.raku
/ |(,).raku
Напечатайте значение таким образом, чтобы его потенциально можно было оценить.
Empty
– это конкретный экземпляр пустой квитанции, который имеет специальную обработку во время выполнения.
|().List
Получите список вместо слипа.
Это должно быть здесь, потому что слип является подклассом списка, поэтому обычно он просто возвращает сам себя.
Ничто из этого не имеет ничего общего с сведением Slip в список.
Обратите внимание, что даже в комментарии вверху указано, что это обычный список.
Вы можете сгладить его, если используете список (в данном случае List
или Range
) в качестве индекса.
@a[2, ] = |(3,4); # [Any, Any, 3]
@a[2, 3] = |(3,4); # [Any, Any, 3, 4]
@a[2..3] = |(3,4); # [Any, Any, 3, 4]
Используя индекс списка, вы сообщаете Раку, что результатом операции @a[…]
является список, а не одно значение.
Это не имеет ничего общего с тем, что rvalue является Slip. Это связано с тем, что rvalue является подклассом List.
Чуть более явно.
my $l-value := @a[2]; # contains the actual Scalar object in the array
my $r-value := |(3,4);
$l-value = $r-value;
Это в основном то же самое, что и ваш код
@a[2] = |(3,4);
@a[2] =
— это две отдельные операции. Индексация, а затем присвоение
@a[2]
возвращает скалярный контейнер, затем =
присваивает значение справа этому единственному контейнеру.
Чтобы сгладить Slip, заданию потребуется доступ к самому массиву. Чего-то в нем нет. Он имеет доступ только к единственному скалярному контейнеру. Таким образом, он вставляет Slip в Scalar, который у него есть. (На самом деле назначение на самом деле не знает, что скаляр даже является членом массива.)
Когда вы связываетесь, вы делаете что-то немного другое. Дело в том, что привязка должна быть более низкого уровня, чем обычное присваивание. Таким образом, было бы даже более вероятно просто вставить в одно место вместо выравнивания.
Чтобы сделать что-то другое, @a[2]
должен вернуть прокси, который знает, как сгладить Slip в массив.
Если вы действительно хотите это сделать, используйте splice
, так как он имеет ссылку на массив.
my @a = 1, |(2, 3);
@a.splice: 2, 1, |(3,4);
Опять же, это не особенное из-за скольжения.
person
Brad Gilbert
schedule
06.06.2021