Как я могу нарезать фигурный массив в Perl 6? - PullRequest
0 голосов
/ 16 мая 2018

Я могу сделать фигурный (фиксированный) массив:

my @array[3;3] = (
    < 1 2 3 >,
    < 4 5 6 >,
    < 7 8 9 >
    );

say @array;       # [[1 2 3] [4 5 6] [7 8 9]]
say @array[1;1];  # 5

Как я могу нарезать это, чтобы получить любой конкретный столбец или диагональ, которую я хочу (строки легко)?

Как превратить список индексов в каждом измерении в правильную вещь, заключенную в квадратные скобки?

И, конечно же, есть какой-то причудливый синтаксис, который не позволит мне сделать что-то сложное:

my @diagonal = gather {
    my @ends = @array.shape.map: { (0 ..^ $^a).List };
    for [Z] @ends {
        take @array[ $_ ] # how do I make that $_[0];$_[1];...
        };
    }

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Как я могу нарезать это, чтобы получить любой конкретный столбец или диагональ, которую я хочу?

Насколько я знаю, в настоящее время вы не можете использовать синтаксис срезов с фигурными массивами (несмотря на ваш комментарий "(строки просты)", который смущает меня за мой комментарий к вашему сообщению ).

Очевидное решение - сбросить форму и использовать синтаксис среза:

my @array = ( < 1 2 3 >, < 4 5 6 >, < 7 8 9 > );

say @array[1];         # 4 5 6 (second row)
say @array[1;*];       # same
say @array[*;1];       # 2 5 8 (second column)

Если вы хотите сохранить безопасность проверки границ при использовании фасонного массива (и / или совместимость массива C с фасонным собственным массивом, если я прав, это так), то вам, вероятно, придется хранить две копии массива вокруг, используя один, чтобы сохранить желаемый аспект массивов, другой - нарезать.

Как превратить список индексов в каждом измерении в правильную вещь, заключенную в квадратные скобки?

Каждый размерный срез перед последним листом должен отделяться от следующего ;.

Мне пока неясно, является ли это ; разделителем операторов (в нижнем индексе) или индикатором списка списка, или как программно преобразовать список индексов в эту форму. (Расследование продолжается.)

И, конечно, есть какой-то причудливый синтаксис, который не позволил бы мне сделать что-то сложное [для диагонального среза]:

say @array[*;{$++}];   # 1 5 9 (diagonal)

Первое разделенное поле ; в индексе массива [...] соответствует первому измерению в массиве, то есть строкам в массиве.

Указание * означает, что вы хотите включить все строки, а не указывать конкретные строки.

Последнее поле соответствует листьям нижнего индекса, фактическим элементам, к которым осуществляется доступ.

Сначала я попробовал просто $++, а не {$++}, но это дало мне нулевой столбец для всех элементов, вероятно, потому что language / roast и / или Rakudo оценивают значение скалярного индекса только один раз за вызов оператора индекса [...]. .

Затем я решил, что если индекс равен Callable , он будет вызван и может вызываться один раз в строке. И это сработало.

Я думаю, что соответствует этот код в Rakudo .

На первый взгляд это означает, что вы не можете использовать Callable для расчета среза листа, и я отмечаю, что жаркое нарезки для "вычисленных индексов" не включает использование Callable. Возможно, я просто не смотрю на это правильно.

0 голосов
/ 16 мая 2018

Вы, вероятно, видели, что это возвращает еще не реализованную ошибку (которая была вставлена ​​ для устранения этой ошибки ;

Partially dimensioned views of shaped arrays not yet implemented. Sorry.

В этом случае может быть лучше просто расформировать массив и использовать более традиционный подход:

use v6;

my @array = (
    < 1 2 3 >,
    < 4 5 6 >,
    < 7 8 9 >
    );

my @diagonal = gather {
    my @ends = ((0,0),(1,1),(2,2));
    for @ends -> @indices {
        take @array[ @indices[0] ][@indices[1]];
    };
}
say @diagonal;

Глядя на краткий обзор по теме , я бы сказал, что подход на самом деле не указан. Поэтому, когда все сказано и сделано, вам, вероятно, придется использовать либо EVAL, либо макросы (когда они, в конце концов, будут реализованы, конечно ...)

...