Uma solução barebones
Vamos começar com uma solução muito simples para imprimir uma essência de uma sequência. Ele não trata das especificidades que você adicionou à sua pergunta, mas é um bom ponto de partida:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
Ao contrário .kv
, o que converte seu invocante no formulário key1, value1, key2, value2, key3, value3, ...
, ou seja, 6 elementos se o invocante contiver 3 elementos, .pairs
converte o invocante no formulário key1 => value1, key2 => value2, key3 => value3, ...
.
Eu usei em .pairs
vez de em .kv
parte porque isso significava que eu poderia usar ».gist
mais tarde no código para obter uma key1 => value1
exibição agradável para cada elemento sem esforço . Vamos modificar isso abaixo, mas este é um bom começo idiomático.
As chamadas .head
e .tail
são a maneira idiomática de criar pequenas listas do primeiro e do último N elementos a partir de uma lista invocante (desde que não seja preguiçoso; mais sobre isso em breve).
Dada esta solução inicial, say seq-range-gist (0,1 ... Inf)[^10]
exibe:
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
Em seguida, queremos poder "soltar apenas o primeiro elemento ... da saída impressa". Infelizmente say seq-range-gist (0,1 ... Inf)[1..9]
exibe:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
Queremos que o número à esquerda do =>
retenha a numeração da sequência original. Para habilitar isso, dividimos a sequência subjacente do intervalo que queremos extrair. Nós adicionamos um segundo parâmetro / argumento @range
e anexamos [@range]
à segunda linha do sub:
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
Agora podemos escrever say seq-range-gist (0,1 ... Inf), 1..9
para exibir:
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
Na sua pergunta, você usou o formato em aINDEX = VALUE
vez de INDEX => VALUE
. Para permitir a personalização da essência, adicionamos um terceiro &gist
parâmetro / argumento de rotina e chamamos isso em vez do .gist
método incorporado :
sub seq-range-gist ( @seq, @range, :&gist ) {
my @pairs = @seq.pairs[@range];
join "\n", @pairs.head(3)».&gist, '...', @pairs.tail(2)».&gist
}
Observe como as invocações de "método" no corpo de seq-range-gist
sub são agora .&gist
, não .gist
. A sintaxe .&foo
chama um sub &foo
(que normalmente é chamado apenas por escrito foo
), passando o invocante à esquerda do .
como $_
argumento para o sub.
Observe também que eu fiz o &gist
parâmetro nomeado, precedendo-o com a :
.
Então agora é say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
exibido:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
Adicionando polonês
O restante desta resposta é um material bônus para os leitores que se preocupam com o polimento.
say seq-range-gist (0, 1, 2, 3), ^3
exibe:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
Opa E mesmo que houvesse mais pares do que a cabeça e a cauda combinadas, pelo menos não tivéssemos linhas repetidas, ainda não faria sentido usar a head, ..., tail
abordagem para eliminar apenas um ou dois elementos. Vamos alterar a última declaração no sub-corpo para eliminar esses problemas:
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
Em seguida, seria bom se o sub fizesse algo útil se chamado sem um intervalo ou essência. Podemos principalmente corrigir isso, fornecendo os parâmetros @range
e &gist
padrões adequados:
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
Se não@seq
for preguiçoso , o padrão será o intervalo completo de . Se for infinito (nesse caso, também é preguiçoso), o padrão de até 100 está bom. Mas e se for preguiçoso, mas produzir menos de 100 valores definidos? Para cobrir este caso, anexamos à declaração: @range
@seq
@seq
@seq
.grep: *.value.defined
@pairs
my @pairs = @seq.pairs[@range].grep: *.value.defined;
Outra melhoria simples seria parâmetros opcionais de cabeça e cauda, levando a uma solução final polida:
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)
}