Solusi barebones
Mari kita mulai dengan solusi yang sangat sederhana untuk mencetak inti dari suatu urutan. Itu tidak berurusan dengan spesifik yang telah Anda tambahkan ke pertanyaan Anda, tetapi itu adalah titik awal yang baik:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
Tidak seperti .kv
, yang mengubah invosinya ke dalam bentuk key1, value1, key2, value2, key3, value3, ...
, yaitu 6 elemen jika invosinya mengandung 3 elemen, .pairs
mengubah invosanya menjadi bentuk key1 => value1, key2 => value2, key3 => value3, ...
.
Saya menggunakan .pairs
bukan .kv
sebagian karena itu berarti saya bisa menggunakan ».gist
nanti dalam kode untuk dengan mudah mendapatkan key1 => value1
tampilan yang bagus untuk setiap elemen. Kami akan memodifikasi itu di bawah ini tetapi ini adalah awal yang bagus untuk memulai.
The .head
dan .tail
panggilan adalah cara idiomatik untuk membuat daftar kecil dari yang pertama dan terakhir unsur N dari daftar invocant (asalkan jangan malas; lebih lanjut tentang bahwa dalam mo a).
Dengan solusi awal ini, say seq-range-gist (0,1 ... Inf)[^10]
menampilkan:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Selanjutnya, kami ingin dapat "membuang elemen pertama ... dari hasil cetak". Sayangnya say seq-range-gist (0,1 ... Inf)[1..9]
menampilkan:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Kami ingin nomor di sebelah kiri =>
mempertahankan penomoran urutan asli. Untuk mengaktifkan ini, kami membagi urutan yang mendasarinya dari rentang yang ingin kami ekstrak. Kami menambahkan parameter / argumen kedua @range
, dan menambahkan [@range]
ke baris kedua dari sub:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Sekarang kita dapat menulis say seq-range-gist (0,1 ... Inf), 1..9
untuk ditampilkan:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
Dalam pertanyaan Anda, Anda menggunakan format aINDEX = VALUE
daripada INDEX => VALUE
. Untuk membolehkan kustomisasi intisari, kami menambahkan &gist
parameter / argumen rutin ketiga dan meminta itu alih-alih .gist
metode bawaan:
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
Perhatikan bagaimana pemanggilan "metode" dalam tubuh seq-range-gist
sub sekarang .&gist
, tidak .gist
. Sintaks .&foo
memanggil sub &foo
(yang biasanya dipanggil dengan menulis adil foo
), melewati pemohon di sebelah kiri .
sebagai $_
argumen ke sub.
Perhatikan juga bahwa saya telah membuat &gist
parameter bernama satu dengan mendahului dengan a :
.
Jadi sekarang say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
tampilkan:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Menambahkan cat
Sisa dari jawaban ini adalah bahan bonus untuk pembaca yang peduli dengan bahasa Polandia.
say seq-range-gist (0, 1, 2, 3), ^3
menampilkan:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Ups. Dan bahkan jika ada lebih banyak pasangan daripada gabungan antara kepala dan ekor, jadi setidaknya kita tidak mendapatkan garis yang diulang, masih tidak ada gunanya menggunakan head, ..., tail
pendekatan untuk menghilangkan hanya satu atau dua elemen. Mari kita ubah pernyataan terakhir di sub tubuh untuk menghilangkan masalah ini:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Selanjutnya, alangkah baiknya jika sub melakukan sesuatu yang berguna jika dipanggil tanpa range atau intisari. Kami sebagian besar dapat memperbaikinya dengan memberikan @range
dan &gist
parameter default yang sesuai:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Jika @seq
ini tidak malas , maka @range
default ke berbagai @seq
. Jika @seq
tidak terbatas (dalam hal ini juga malas), maka standar hingga 100 baik-baik saja. Tetapi bagaimana jika @seq
malas tetapi menghasilkan kurang dari 100 nilai yang ditentukan? Untuk membahas kasus ini kami menambahkan .grep: *.value.defined
ke @pairs
deklarasi:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Peningkatan sederhana lainnya adalah parameter kepala dan ekor opsional, yang mengarah ke solusi akhir yang dipoles:
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)
}