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, .pairsmengubah invosanya menjadi bentuk key1 => value1, key2 => value2, key3 => value3, ....
Saya menggunakan .pairsbukan .kvsebagian karena itu berarti saya bisa menggunakan ».gistnanti dalam kode untuk dengan mudah mendapatkan key1 => value1tampilan yang bagus untuk setiap elemen. Kami akan memodifikasi itu di bawah ini tetapi ini adalah awal yang bagus untuk memulai.
The .headdan .tailpanggilan 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..9untuk ditampilkan:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
Dalam pertanyaan Anda, Anda menggunakan format aINDEX = VALUEdaripada INDEX => VALUE. Untuk membolehkan kustomisasi intisari, kami menambahkan &gistparameter / argumen rutin ketiga dan meminta itu alih-alih .gistmetode 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-gistsub sekarang .&gist, tidak .gist. Sintaks .&foomemanggil sub &foo (yang biasanya dipanggil dengan menulis adil foo), melewati pemohon di sebelah kiri .sebagai $_argumen ke sub.
Perhatikan juga bahwa saya telah membuat &gistparameter 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, ..., tailpendekatan 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 @rangedan &gistparameter default yang sesuai:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Jika @seqini tidak malas , maka @rangedefault ke berbagai @seq. Jika @seqtidak terbatas (dalam hal ini juga malas), maka standar hingga 100 baik-baik saja. Tetapi bagaimana jika @seqmalas tetapi menghasilkan kurang dari 100 nilai yang ditentukan? Untuk membahas kasus ini kami menambahkan .grep: *.value.definedke @pairsdeklarasi:
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)
}