TL; DR Привязка выполняется быстрее, чем назначение, поэтому, возможно, это лучшее решение для вашей проблемы:
:(@ra1, @ra2) := <10 20>.map(...);
Назначение / копирование
Упрощение,Ваш нерабочий код:
(@listvar1, @listvar2) = list1, list2;
В инфиксе P6 =
означает присвоение / копирование списка значений справа от =
в один или несколько из контейнер переменных слева от =
.
Если переменная слева связана с Scalar
контейнером , то она примет одинвещь.Затем процесс копирования начинает нацеливаться на следующую переменную контейнера.
Если переменная слева связана с Array
контейнером , то она примет все оставшиеся значения.Итак, ваша первая переменная массива получает как list1
, так и list2
.Это не то, что вы хотите.
Упрощенно, вот ответ Кристофа:
@listvar1, @listvar2 Z= list1, list2;
Отложив =
на мгновение, Z
- это инфиксная версия zip
рутина .Это как ( физический zip , соединяющий последовательные аргументы слева и справа. При использовании с оператором он применяет этот оператор к паре. Таким образом, вы можете прочитать выше Z=
как:
@listvar1 = list1;
@listvar2 = list2;
Работа выполнена.
Но назначение в Array
контейнеров влечет за собой:
По отдельности копирование какмного отдельных элементов списка, так как в контейнерах. (В коде в вашем примере list1
и list2
содержат 5 элементов каждый, так что всего будет 10 операций копирования.)
Принудительное изменение размеров контейнеров для размещения элементов.
Удвоение памяти, используемой элементами (исходные элементы списка и скопированные дубликаты)в Array
элементов).
Проверка того, что тип каждого элемента соответствует ограничению на тип элемента.
Назначение в целом многомедленнее и требует больше памяти, чем привязка ...
Binding
:(@listvar1, @listvar2) := list1, list2;
Оператор :=
связывает аргументы справа от того, что слева от него.
Если естьодна переменная слева, тогда все особенно просто.После привязки переменная теперь относится именно к тому, что справа.(Это особенно просто и быстро - быстрая проверка типа, и она сделана.)
Но в нашем случае это не так.
Binding также принимает автономный литерал подписи слева от него.:(...)
в моем ответе - автономный Signature
литерал.
(подписи обычно прикрепляются к подпрограмме без префикса двоеточия. Например, в sub foo (@var1, @var2) {}
(@var1, @var2)
part - это сигнатура, прикрепленная к подпрограмме foo
. Но, как вы можете видеть, можно написать сигнатуру отдельно и дать P6 знать, что это сигнатура, добавив перед парой двоеточия двоеточие.в подписи, должно быть, уже было объявлено.)
Если слева находится литерал подписи, то привязка происходит в соответствии с той же логикой, что и при привязке аргументов в обычных вызовах к подписи принимающей подпрограммы.(Действительно, он использует тот же путь кода в компиляторе.)
Таким образом, в результате переменные получают значения, которые они будут иметь внутри этого подпрограммы:
sub foo (@listvar1, @listvar2) { }
foo list1, list2;
, чтосказать, что эффект такой же, как:
@listvar1 := list1;
@listvar2 := list2;
Опять же, как и с ответом Кристофа, работа выполнена.
Но на этот раз мы избежали большинства накладных расходов, описанных вконец предыдущего раздела.