ベアボーンソリューション
シーケンスの要点を印刷するための非常にシンプルなソリューションから始めましょう。それはあなたがあなたの質問に追加した詳細を扱いませんが、それは良い出発点です:
sub seq-range-gist ( @seq ) {
my @pairs = @seq.pairs;
join "\n", @pairs.head(3)».gist, '...', @pairs.tail(2)».gist
}
とは異なり.kv
、その呼び出し元をフォームに変換しますkey1, value1, key2, value2, key3, value3, ...
。つまり、その呼び出し元が3つの要素を含む場合、6つの要素は、.pairs
その呼び出し元をフォームに変換しkey1 => value1, key2 => value2, key3 => value3, ...
ます。
一部の.pairs
代わりに使用しまし.kv
た。これは».gist
、後でコード内で使用するだけで、key1 => value1
各要素の表示を簡単にできるようになるためです。以下で変更しますが、これは慣用的な出発点として適切です。
通話は(;よりカ月でそのことについて、それは怠惰ではありません提供)インボカントリストから最初と最後のN個の要素の小さなリストを作成するための慣用的な方法です。.head
.tail
この最初のソリューションが与えられると、次のようにsay seq-range-gist (0,1 ... Inf)[^10]
表示されます。
0 => 0
1 => 1
2 => 2
...
8 => 8
9 => 9
次に、「最初の要素だけを...印刷された出力から削除する」ことができるようにしたいと思います。残念ながらsay seq-range-gist (0,1 ... Inf)[1..9]
表示されます:
0 => 1
1 => 2
2 => 3
...
7 => 8
8 => 9
の左側の=>
番号に元のシーケンスの番号付けを保持させたい。これを有効にするには、抽出する範囲から基になるシーケンスを分割します。2番目のパラメーター/引数@range
を追加[@range]
し、サブの2行目に追加します。
sub seq-range-gist ( @seq, @range ) {
my @pairs = @seq.pairs[@range];
これでsay seq-range-gist (0,1 ... Inf), 1..9
、表示を書き込むことができます。
1 => 1
2 => 2
3 => 3
...
8 => 8
9 => 9
あなたの質問では、aINDEX = VALUE
ではなく形式を使用しましたINDEX => VALUE
。要旨のカスタマイズを可能にするために、3番目の&gist
ルーチンのパラメーター/引数を追加し、組み込み.gist
メソッドの代わりにそれを呼び出します。
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 の本体の「メソッド」呼び出しが、.&gist
ではなくになって.gist
いることに注意してください。構文.&foo
はsubを 呼び出し&foo
(通常はjustを書き込むことで呼び出されますfoo
)、その左側の呼び出し元を引数.
としてsubに渡し$_
ます。
また、&gist
パラメータの前にを付けて、パラメータを名前付きのものにしたことにも注意してください:
。
だから今say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
表示されます:
a1 = 1
a2 = 2
a3 = 3
...
a8 = 8
a9 = 9
ポリッシュを追加する
この答えの残りは、磨きを気にする読者のためのボーナス資料です。
say seq-range-gist (0, 1, 2, 3), ^3
表示:
0 => 0
1 => 1
2 => 2
...
1 => 1
2 => 2
おっとっと。また、ヘッドとテールの組み合わせよりも多くのペアがあったとしても、少なくともラインが繰り返されなかったとしても、head, ..., tail
1つまたは2つの要素だけを削除するアプローチを使用しても意味がありません。サブボディの最後のステートメントを変更して、これらの問題を排除しましょう。
join "\n",
@pairs < $head + $tail + 3 # Of course, the 3 is a bit arbitrary
?? @pairs».&gist
!! (@pairs.head($head)».&gist, '...', @pairs.tail($tail)».&gist)
次に、範囲または要旨なしで呼び出された場合、サブが何か便利なことをするといいでしょう。@range
と&gist
パラメータに適切なデフォルトを与えることで、ほとんどの場合それを修正できます。
sub seq-range-gist (
@seq,
@range = @seq.is-lazy ?? ^100 !! ^@seq,
:&gist = { .gist }
) {
@seq
が遅延でない 場合、デフォルトでの全範囲になります。が無限の場合(この場合も遅延です)、最大100のデフォルトで問題ありません。しかし、怠惰であるにもかかわらず、定義された値が100未満の場合はどうなりますか?このケースをカバーするために、宣言に追加します。@range
@seq
@seq
@seq
.grep: *.value.defined
@pairs
my @pairs = @seq.pairs[@range].grep: *.value.defined;
別の単純な改善は、オプションのヘッドとテールのパラメーターであり、最終的な洗練されたソリューションにつながります。
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)
}