. 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
子程序体中的 "method" 调用现在是 .&gist
,而不是 .gist
。语法 .&foo
调用了一个 sub &foo
(通常通过编写 foo
来调用),并将左侧的 invocant 作为 $_
参数传递给 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”方法来省略一个或两个元素仍然是没有意义的。让我们改变子体中的最后一条语句以消除这些问题:
join "\n",
@pairs < $head + $tail + 3
?? @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
不是懒惰的话,@range
默认为@seq
的完整范围。如果@seq
是无限的(在这种情况下它也是懒惰的),那么默认的最多100个就可以了。但是如果@seq
是懒惰的,但产生的定义值少于100个怎么办?为了涵盖这种情况,我们将.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)
}