Barebone çözümü
Bir sekansın özünü yazdırmak için çok basit bir çözümle başlayalım. Sorunuza eklediğiniz özelliklerle ilgilenmiyor, ancak iyi bir başlangıç noktası:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
.kv
Invocanını forma dönüştürenlerin aksine , key1, value1, key2, value2, key3, value3, ...
invocan 3 element içeriyorsa 6 element, .pairs
invosanını forma dönüştürür key1 => value1, key2 => value2, key3 => value3, ...
.
Bunun .pairs
yerine .kv
kısmen kullandığım ».gist
için, kodda daha sonra key1 => value1
her öğeye zahmetsizce güzel bir ekran almak için kullanabileceğim anlamına geliyordu . Bunu aşağıda değiştireceğiz, ancak bu iyi bir deyimsel başlangıç.
.head
ve.tail
çağrılar bir invocant listeden ilk ve son N elemanlarının küçük listeleri oluşturmak için deyimsel yoludur (o tembel değil sağlanan; daha bu konu hakkında bir mo).
Bu ilk çözüm verildiğinde aşağıdakileri say seq-range-gist (0,1 ... Inf)[^10]
görüntüler:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Daha sonra, "sadece ilk öğeyi ... basılı çıktıdan düşürmek" istiyoruz. Ne yazık ki say seq-range-gist (0,1 ... Inf)[1..9]
görüntüler:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Solundaki sayının =>
orijinal dizinin numaralandırmasını korumasını istiyoruz . Bunu etkinleştirmek için temel diziyi ayıklamak istediğimiz aralıktan ayırırız. İkinci bir parametre / bağımsız değişken ekliyoruz ve alt @range
öğenin [@range]
ikinci satırına ekliyoruz :
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Şimdi say seq-range-gist (0,1 ... Inf), 1..9
görüntülemek için yazabiliriz :
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
Sorunuzda biçimi kullanmak aINDEX = VALUE
yerine kullandınız INDEX => VALUE
. Gist'in özelleştirilmesine izin vermek için üçüncü bir &gist
rutin parametre / argüman ekliyoruz ve bunu yerleşik .gist
yöntem yerine çağırıyoruz :
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
Sub gövdesindeki "yöntem" çağrılarının şimdi nasıl olduğuna .&gist
dikkat edin .gist
. Sözdizimi .&foo
bir çağırır alt &foo
(tipik olarak, sadece yazılı çağrılır foo
solunda invocant geçen) .
bir şekilde $_
alt argüman.
Ayrıca &gist
parametrenin bir ile başlayarak adlandırılmış bir tane yaptığımı unutmayın :
.
Şimdi say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
görüntülenir:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Lehçe ekleme
Bu cevabın geri kalanı lehçeyi önemseyen okuyucular için bonus materyal.
say seq-range-gist (0, 1, 2, 3), ^3
görüntüler:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Hata. Ve kafa ve kuyruktan daha fazla çift olsa bile, en azından tekrarlanan çizgiler alamadık, head, ..., tail
sadece bir veya iki elementi elide etme yaklaşımını kullanmak yine de anlamsız olurdu . Bu sorunları ortadan kaldırmak için alt gövdedeki son ifadeyi değiştirelim:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Sonra, alt aralık veya gist olmadan çağrılırsa yararlı bir şey yapsaydı iyi olurdu. Bunu çoğunlukla @range
ve &gist
parametrelerine uygun varsayılanlar vererek düzeltebiliriz :
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Eğer @seq
bir değil tembel sonra, @range
tam kapsamlı varsayılan @seq
. Eğer @seq
bir sonsuz (bu durumda o da tembeldir), sonra 100 kadar varsayılan gayet iyi. Peki ya @seq
tembel ancak 100'den az tanımlanmış değer verirse ne olur ? Bu vakayı kapsamak .grep: *.value.defined
için @pairs
bildirime ekliyoruz:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Başka bir basit gelişme, isteğe bağlı kafa ve kuyruk parametreleri olacak ve nihai cilalı bir çözüme yol açacaktır:
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)
}