Баскетбольное решение
Давайте начнем с очень простого решения для печати сути последовательности. Это не касается специфики, которую вы добавили в свой вопрос, но это хорошая отправная точка:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
В отличие от .kv, который преобразует свой инвокант в форму key1, value1, key2, value2, key3, value3, ..., то есть 6 элементов, если его инвокант содержит 3 элемента, .pairsпреобразует свой инвокант в форму key1 => value1, key2 => value2, key3 => value3, ....
Я использовал .pairsвместо .kvчастично, потому что это означало, что я мог бы ».gistпозже использовать в коде, чтобы без особых усилий получить хорошее key1 => value1отображение для каждого элемента. Мы изменим это ниже, но это хорошее идиоматическое начало.
.headИ .tailзвонки идиоматических способ создать небольшие списки первых и последних N элементов из списка invocant ( при условии , что это не лень, больше о том , что в мес).
Учитывая это первоначальное решение, say seq-range-gist (0,1 ... Inf)[^10]отображает:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Далее, мы хотим иметь возможность «удалить только первый элемент ... из печатной продукции». К сожалению say seq-range-gist (0,1 ... Inf)[1..9]отображает:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Мы хотим, чтобы число слева от =>сохранило нумерацию исходной последовательности. Чтобы включить это, мы отделяем основную последовательность от диапазона, который мы хотим извлечь. Мы добавляем второй параметр / аргумент @rangeи добавляем [@range]ко второй строке подпрограммы:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Теперь мы можем написать say seq-range-gist (0,1 ... Inf), 1..9для отображения:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
В своем вопросе вы использовали формат, aINDEX = VALUEа не INDEX => VALUE. Чтобы разрешить настройку сущности, мы добавляем третий &gistстандартный параметр / аргумент и вызываем его вместо встроенного .gistметода:
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
Обратите внимание, что вызовы "method" в теле seq-range-gistsub теперь .&gistне являются .gist. Синтаксис .&fooвызывает подпрограмму &foo (которая обычно вызывается путем написания просто foo), передавая вызов слева .в качестве $_аргумента подпрограмме.
Также обратите внимание, что я сделал &gistпараметр именованным, поставив перед ним символ :.
Итак, теперь say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }отображает:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Добавляя польский
Остальная часть этого ответа - бонусный материал для читателей, которым небезразлична полька.
say seq-range-gist (0, 1, 2, 3), ^3 дисплеи:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
К сожалению. И даже если бы было больше пар, чем головы и хвоста вместе, поэтому, по крайней мере, мы не получили повторяющихся линий, было бы бессмысленно использовать head, ..., tailподход, чтобы исключить только один или два элемента. Давайте изменим последнее утверждение в под-теле, чтобы устранить эти проблемы:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Далее, было бы неплохо, если бы сабвуфер сделал что-то полезное, если бы вызывался без диапазона или сути. Мы можем главным образом исправить, давая @rangeи &gistпараметры , подходящие по умолчанию:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Если @seqэто не ленив , то по @rangeумолчанию в полном диапазоне @seq. Если @seqэто бесконечно (в этом случае это также лениво), то по умолчанию до 100 по умолчанию. Но что, если @seqэто ленивый, но дает менее 100 определенных значений? Чтобы охватить этот случай, мы добавляем .grep: *.value.definedк @pairsдекларации:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Еще одно простое улучшение - необязательные параметры головы и хвоста, приводящие к окончательному полированному решению:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:$head = 3,
:$tail = 2,
:&gist = { .gist }
) {
my @pairs = @seq.pairs[@range].grep: *.value.defined;
join "\n",
@pairs <= $head + $tail + 2
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
}