Розчин босоніжок
Почнемо з дуже простого рішення для друку суті послідовності. Він не стосується особливостей, які ви додали до свого питання, але це хороша відправна точка:
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
}
Зверніть увагу, як зараз виклики "методу" в тілі seq-range-gist
підрозділу .&gist
, ні .gist
. Синтаксис .&foo
викликає суб &foo
(який , як правило , викликається шляхом запису тільки foo
), передаючи invocant на зліва від .
як $_
аргумент на південь.
Зауважте також, що я зробив &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)
}