Une solution barebones
Commençons par une solution très simple pour imprimer l'essentiel d'une séquence. Il ne traite pas des détails que vous avez ajoutés à votre question, mais c'est un bon point de départ:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
Contrairement .kv, qui convertit son invocant en forme key1, value1, key2, value2, key3, value3, ..., c'est-à-dire 6 éléments si son invocant contient 3 éléments, .pairsconvertit son invocant en forme key1 => value1, key2 => value2, key3 => value3, ....
J'ai utilisé .pairsau lieu de .kvpartiellement parce que cela signifiait que je pouvais simplement utiliser ».gistplus tard dans le code pour obtenir sans effort un bel key1 => value1affichage pour chaque élément. Nous allons modifier cela ci-dessous mais c'est un bon début idiomatique.
Le .headet.tail appels sont le moyen idiomatique de créer de petites listes des premier et dernier N éléments à partir d'une liste invocante (à condition que ce ne soit pas paresseux; plus à ce sujet dans un mois).
Compte tenu de cette solution initiale, say seq-range-gist (0,1 ... Inf)[^10]affiche:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Ensuite, nous voulons pouvoir "supprimer uniquement le premier élément ... de la sortie imprimée". say seq-range-gist (0,1 ... Inf)[1..9]Affiche malheureusement :
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Nous voulons que le numéro à gauche de la =>conserve la numérotation de la séquence d'origine. Pour activer cela, nous séparons la séquence sous-jacente de la plage que nous voulons extraire. Nous ajoutons un deuxième paramètre / argument @range, et ajoutons [@range]à la deuxième ligne du sous:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Maintenant, nous pouvons écrire say seq-range-gist (0,1 ... Inf), 1..9pour afficher:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
Dans votre question, vous avez utilisé le format aINDEX = VALUEplutôt que INDEX => VALUE. Pour permettre la personnalisation de l'essentiel, nous ajoutons un troisième &gistparamètre / argument de routine et l'invoquons à la place de la .gistméthode intégrée :
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
Notez comment les invocations de "méthode" dans le corps de seq-range-gistsub ne sont .&gistplus .gist. La syntaxe .&fooinvoque un sous - marin&foo (qui est généralement appelé en écrivant simplement foo), en passant l'invocant à gauche de l' argument .comme $_argument au sous-marin.
Notez également que j'ai rendu le &gistparamètre nommé en le précédant d'un :.
say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }Affiche maintenant :
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Ajout de vernis
Le reste de cette réponse est du matériel bonus pour les lecteurs qui se soucient du polonais.
say seq-range-gist (0, 1, 2, 3), ^3 affiche:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Oops. Et même s'il y avait plus de paires que la tête et la queue combinées, donc au moins nous n'avions pas de lignes répétées, il serait toujours inutile d'utiliser l' head, ..., tailapproche pour élider un ou deux éléments. Modifions la dernière instruction du sous-corps pour éliminer ces problèmes:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Ensuite, ce serait bien si le sous-marin faisait quelque chose d'utile s'il était appelé sans plage ni contenu. Nous pouvons principalement résoudre ce problème en donnant aux paramètres @rangeet &gistles valeurs par défaut appropriées:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Si @seqn'est pas paresseux , par @rangedéfaut, la plage complète de @seq. Si @seqest infini (auquel cas il est également paresseux), la valeur par défaut jusqu'à 100 est correcte. Mais que faire si @seqest paresseux mais donne moins de 100 valeurs définies? Pour couvrir ce cas, nous annexons .grep: *.value.definedà la @pairsdéclaration:
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Une autre amélioration simple serait les paramètres facultatifs de tête et de queue, conduisant à une solution finale polie:
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)
}