Eine Barebone-Lösung
Beginnen wir mit einer sehr einfachen Lösung zum Drucken eines Kerns einer Sequenz. Es geht nicht um die Details, die Sie Ihrer Frage hinzugefügt haben, aber es ist ein guter Ausgangspunkt:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
Im Gegensatz dazu .kv, das seinen Invokanten in die Form konvertiert key1, value1, key2, value2, key3, value3, ..., dh 6 Elemente, wenn sein Invokant 3 Elemente enthält,.pairs seinen Invokanten in das Formular key1 => value1, key2 => value2, key3 => value3, ....
Ich habe .pairsstatt .kvteilweise verwendet, weil es bedeutete, dass ich ».gistspäter im Code mühelos eine schöne key1 => value1Anzeige für jedes Element erhalten konnte. Wir werden das unten ändern, aber dies ist ein guter idiomatischer Start.
Die .headund .tail-Aufrufe sind die idiomatische Methode, um kleine Listen der ersten und letzten N Elemente aus einer Invocant-Liste zu erstellen (vorausgesetzt, es ist nicht faul; mehr dazu in einem Mo).
In Anbetracht dieser anfänglichen Lösung werden say seq-range-gist (0,1 ... Inf)[^10]Folgendes angezeigt:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Als nächstes möchten wir in der Lage sein, "nur das erste Element ... aus der gedruckten Ausgabe zu löschen". Leider say seq-range-gist (0,1 ... Inf)[1..9]zeigt:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Wir möchten, dass die Nummer links von der =>die Nummerierung der ursprünglichen Sequenz beibehält. Um dies zu ermöglichen, teilen wir die zugrunde liegende Sequenz aus dem Bereich auf, den wir extrahieren möchten. Wir fügen einen zweiten Parameter / ein zweites Argument hinzu @rangeund hängen [@range]an die zweite Zeile des Unterabschnitts an:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Jetzt können wir schreiben, say seq-range-gist (0,1 ... Inf), 1..9um anzuzeigen:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
In Ihrer Frage haben Sie aINDEX = VALUEeher das Format als verwendet INDEX => VALUE. Um die Anpassung des Kerns zu ermöglichen, fügen wir einen dritten &gistRoutineparameter / Argument hinzu und rufen diesen anstelle der integrierten .gistMethode auf:
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
Beachten Sie, wie die "Methoden" -Aufrufe im Hauptteil von seq-range-gistsub jetzt .&gistnicht mehr sind .gist. Die Syntax .&fooruft ein Sub auf &foo (das normalerweise durch fooeinfaches Schreiben aufgerufen wird ) und übergibt den Invokanten links von .als $_Argument an das Sub.
Beachten Sie auch, dass ich den &gistParameter benannt habe, indem ich ihm ein vorangestellt habe :.
So say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }zeigt nun :
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Politur hinzufügen
Der Rest dieser Antwort ist Bonusmaterial für Leser, die sich für Politur interessieren.
say seq-range-gist (0, 1, 2, 3), ^3 zeigt an:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Hoppla. Und selbst wenn es mehr Paare als Kopf und Schwanz zusammen gäbe, so dass wir zumindest keine wiederholten Linien bekamen, wäre es immer noch sinnlos, head, ..., tailnur ein oder zwei Elemente zu entfernen. Lassen Sie uns die letzte Anweisung im Unterkörper ändern, um diese Probleme zu beseitigen:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Als nächstes wäre es schön, wenn das U-Boot etwas Nützliches tun würde, wenn es ohne Reichweite oder Kern aufgerufen würde. Wir können das meistens beheben, indem wir den @rangeund &gistParametern geeignete Standardeinstellungen geben:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Wenn @seqes nicht faul ist , wird @rangestandardmäßig der gesamte Bereich von verwendet @seq. Wenn @seqes unendlich ist (in diesem Fall ist es auch faul), ist die Standardeinstellung von bis zu 100 in Ordnung. Aber was ist, wenn @seqes faul ist, aber weniger als 100 definierte Werte liefert? Um diesen Fall abzudecken, fügen wir .grep: *.value.definedder @pairsErklärung bei:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Eine weitere einfache Verbesserung wären optionale Kopf- und Schwanzparameter, die zu einer endgültigen polierten Lösung führen:
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)
}