Ответ 1
Не совсем уверен, что это так, но похоже, что обе ваши последовательности сохраняются в @ra1
, а @ra2
остается пустым. Это нарушает ограничение типа.
Что работает
@ra1, @ra2 Z= <10 20>.map(...);
Каков правильный синтаксис для назначения Seq (Seq) в несколько типизированных массивов без предварительного назначения Seq скаляру? Seq должен быть как-то сплющен? Это не удается:
class A { has Int $.r }
my A (@ra1, @ra2);
#create two arrays with 5 random numbers below a certain limit
#Fails: Type check failed in assignment to @ra1; expected A but got Seq($((A.new(r => 3), A.n...)
(@ra1, @ra2) =
<10 20>.map( -> $up_limit {
(^5).map({A.new( r => (^$up_limit).pick ) })
});
Не совсем уверен, что это так, но похоже, что обе ваши последовательности сохраняются в @ra1
, а @ra2
остается пустым. Это нарушает ограничение типа.
Что работает
@ra1, @ra2 Z= <10 20>.map(...);
TL; DR Binding быстрее, чем назначение, поэтому, возможно, это лучшее решение вашей проблемы:
:(@ra1, @ra2) := <10 20>.map(...);
Упрощенно, ваш нерабочий код:
(@listvar1, @listvar2) = list1, list2;
В P6 infix =
означает присвоение/копирование списка значений справа от =
в одну или несколько контейнерных переменных слева от =
.
Если переменная слева связана с Scalar
контейнером, то она примет один элемент. Затем процесс копирования начинает нацеливаться на следующую переменную контейнера.
Если переменная слева связана с контейнером Array
, то она примет все оставшиеся значения. Таким образом, ваша первая переменная массива получает и list1
и list2
. Это не то, что вы хотите.
Упрощение, вот ответ Кристофа:
@listvar1, @listvar2 Z= list1, list2;
Отложив =
на мгновение, Z
является инфиксной версией процедуры zip
. Это похоже на (физический почтовый индекс, соединяющий последовательные аргументы слева и справа. При использовании с оператором он применяет этот оператор к паре. Таким образом, вы можете прочитать выше Z=
как:
@listvar1 = list1;
@listvar2 = list2;
Работа выполнена.
Но назначение в контейнеры Array
влечет за собой:
Индивидуальное копирование столько отдельных элементов списка, сколько есть в контейнерах. (В коде вашего примера list1
и list2
содержат по 5 элементов каждый, так что всего будет 10 операций копирования.)
Принудительное изменение размеров контейнеров по мере необходимости для размещения предметов.
Удвоение памяти, используемой элементами (исходные элементы списка и дубликаты, скопированные в элементы Array
).
Проверка того, что тип каждого элемента соответствует ограничению типа элемента.
Назначение обычно намного медленнее и требует больше памяти, чем привязка...
:(@listvar1, @listvar2) := list1, list2;
Оператор :=
связывает аргументы справа от всего, что слева.
Если слева одна переменная, то все особенно просто. После связывания переменная теперь относится именно к тому, что справа. (Это особенно просто и быстро - быстрая проверка типа и все готово.)
Но это не так в нашем случае.
Привязка также принимает автономный литерал подписи слева. Символ :(...)
в моем ответе является отдельным литералом Signature
.
(Сигнатуры обычно присоединяются к подпрограмме без префикса двоеточия. Например, в sub foo (@var1, @var2) {}
(@var1, @var2)
представляет собой подпись, прикрепленную к подпрограмме foo
. Но, как вы можете видите, можно написать сигнатуру отдельно и дать P6 знать ее как сигнатуру, поставив перед парой двоеточий префикс. Главное отличие в том, что любые переменные, перечисленные в сигнатуре, должны быть уже объявлены.)
Когда слева находится литеральный сигнатур, то привязка происходит в соответствии с той же логикой, что и при привязке аргументов в обычных вызовах к получающей обычной подписи. (Действительно, он использует тот же путь кода в компиляторе.)
Таким образом, чистый результат состоит в том, что переменные получают значения, которые они будут иметь внутри этого подпрограммы:
sub foo (@listvar1, @listvar2) { }
foo list1, list2;
то есть эффект такой же как:
@listvar1 := list1;
@listvar2 := list2;
Опять же, как и с ответом Кристофа, работа выполнена.
Но на этот раз мы избежали большинства накладных расходов, описанных в конце предыдущего раздела.