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 .pairs
statt .kv
teilweise verwendet, weil es bedeutete, dass ich ».gist
später im Code mühelos eine schöne key1 => value1
Anzeige für jedes Element erhalten konnte. Wir werden das unten ändern, aber dies ist ein guter idiomatischer Start.
Die .head
und .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 @range
und 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..9
um anzuzeigen:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
In Ihrer Frage haben Sie aINDEX = VALUE
eher das Format als verwendet INDEX => VALUE
. Um die Anpassung des Kerns zu ermöglichen, fügen wir einen dritten &gist
Routineparameter / Argument hinzu und rufen diesen anstelle der integrierten .gist
Methode 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-gist
sub jetzt .&gist
nicht mehr sind .gist
. Die Syntax .&foo
ruft ein Sub auf &foo
(das normalerweise durch foo
einfaches Schreiben aufgerufen wird ) und übergibt den Invokanten links von .
als $_
Argument an das Sub.
Beachten Sie auch, dass ich den &gist
Parameter 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, ..., tail
nur 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 @range
und &gist
Parametern geeignete Standardeinstellungen geben:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Wenn @seq
es nicht faul ist , wird @range
standardmäßig der gesamte Bereich von verwendet @seq
. Wenn @seq
es unendlich ist (in diesem Fall ist es auch faul), ist die Standardeinstellung von bis zu 100 in Ordnung. Aber was ist, wenn @seq
es faul ist, aber weniger als 100 definierte Werte liefert? Um diesen Fall abzudecken, fügen wir .grep: *.value.defined
der @pairs
Erklä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)
}