Как преобразовать параметры цикла в массив фиксированного размера?

Я пытаюсь поместить параметры цикла for в массив ФИКСИРОВАННОГО размера. Вот что я делал (хочу использовать массив @m из 3 элементов):

for (1..19).rotor(3, :partial) -> @m { say @m; } # works, but I cannot specify size of @m

Однако все следующее дает мне ошибки:

for (1..19).rotor(3, :partial) -> @m[0,1,2] { say @m; }
===SORRY!=== Error while compiling:
Variable '@m' is not declared
------> ).rotor(3, :partial) -> @m[0,1,2] { say ⏏@m; }

for (1..19).rotor(3 => -2) -> @m[0..2] { say @m; }
===SORRY!=== Error while compiling:
Variable '@m' is not declared
------> 1..19).rotor(3 => -2) -> @m[0..2] { say ⏏@m; }

for (1..19).rotor(3 => -2) -> @m[3] { say $_; say @m; }
===SORRY!=== Error while compiling:
Variable '@m' is not declared
------> ).rotor(3 => -2) -> @m[3] { say $_; say ⏏@m; }

Итак, как мне указать, что массив @m должен содержать только 3 элемента?

2 ответа

Решение

В названии вопроса упоминается деструктуризация, но речь идет о разборке чего-либо. Например, с его помощью мы могли бы извлечь три элемента:

for (1..19).rotor(3, :partial) -> [$a, $b, $c] {
}

Однако на самом деле это не кажется проблемой деструктурирования, поскольку запрос состоит не в том, чтобы разбить переданный агрегат на части, а преобразовать его в агрегат другого типа.

Посмотрим немного дальше на вопрос:

Я пытаюсь поместить параметры цикла for в массив ФИКСИРОВАННОГО размера.

Дело в том, rotor не производит (изменяемый) Arrays вообще. Вместо этого при написании:

for (1..19).rotor(3, :partial) -> @m {
}

потом @m это List. АListявляется неизменным (и, таким образом, неявно его размер фиксируется при создании), поэтому, если намерение состоит в том, чтобы не было случайного изменения размера, это уже сертификат. К сожалению, конечная цель не была обозначена.

Если действительно хотите превратить переданный неизменяемый List в форме Array, ничего не остается, кроме как присвоить ему новый фиксированный размер Array:

for (1..19).rotor(3, :partial) -> @l {
    my @arr[3] = @l;
}

Конечно, это взорвется, если :partialприводит к остаткам элементов; можно было сделать:

for (1..19).rotor(3, :partial) -> @l {
    my @arr[@l.elems] = @l;
}

Чтобы этого не произошло. Однако, если цель - гарантировать, что все взорвется, если когда-нибудь останутся остатки элементов, то либоwhere:

for (1..19).rotor(3, :partial) -> @m where .elems == 3 {
}

Или, что менее ясно, деструктура на выброс:

for (1..19).rotor(3, :partial) -> @m [$,$,$] {
}

Сделал бы это.

Так что -> @m[3] это то, что вы хотите, но при этом назначаете подпись вашему анонимному блоку, который ожидает сформированный массив, и вы передаете список.

Так что в итоге я мог превратить мой список в сформированный массив.

for (1..19).rotor(3, :partial).map( { Array.new(:shape(3),$_ ) } ) -> @m[3] { say @m; }

И тогда все работает нормально. Возможно, есть способ сделать это лучше.

Другие вопросы по тегам