在Raku中简洁地打印数学系列

Lar*_*een 7 sequence raku

数学级数,例如以此处表示为数组的连续序列:

my @seq = my $a=0, {++$a} ... *;
for @seq[^10].kv {state $f=0; ($^k < 4 or $^k > 7) ?? say "a$^k =  "  ~ $^v !! (say "..." if $f ne 1; $f=1) };
Run Code Online (Sandbox Code Playgroud)

印刷品:

a0 =  0
a1 =  1
a2 =  2
...

a8 =  8
a9 =  9
Run Code Online (Sandbox Code Playgroud)

我的问题:1-是否有一种简单的方法可以只删除第一个元素,即a0 = 0从打印输出中删除?

2-可以使此代码更惯用吗?

谢谢。

Eli*_*sen 6

您可以跳过第一的N值的任何 IterableSequenceskip

for (^5).skip(3) {
    .say
}
# 3
# 4
Run Code Online (Sandbox Code Playgroud)

如果您未指定数字,它将仅跳过一个元素。


jjm*_*elo 6

这可能更惯用:

my @seq = 0, *+1 ... *;
say @seq[^4], @seq[7..10]
Run Code Online (Sandbox Code Playgroud)

您无需在序列中使用词汇变量;任一Whatever占位符变量可以安全序列内使用。然后,您可以简单地选择要打印的序列的元素。哪个返回«(0 1 2 3)(7 8 9 10)?»


rai*_*iph 3

准系统解决方案

\n\n

让我们从一个非常简单的打印序列要点的解决方案开始。它不涉及您添加到问题中的具体细节,但它是一个很好的起点:

\n\n
sub seq-range-gist ( @seq ) {\n  my @pairs = @seq.pairs;\n  join "\\n", @pairs.head(3)\xc2\xbb.gist, \'...\', @pairs.tail(2)\xc2\xbb.gist\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

与 不同.kv,它将其调用者转换为 形式key1, value1, key2, value2, key3, value3, ...,即 6 个元素,如果其调用者包含 3 个元素,.pairs则将其调用者转换为形式key1 => value1, key2 => value2, key3 => value3, ...

\n\n

我使用.pairs而不是.kv部分,因为这意味着我可以\xc2\xbb.gist稍后在代码中使用来轻松地key1 => value1为每个元素获得良好的显示。我们将在下面修改它,但这是一个很好的惯用开始。

\n\n

.head调用.tail是从调用列表创建第一个和最后 N 个元素的小列表的惯用方法(前提是它不是懒惰的;稍后会详细介绍)。

\n\n

给定这个初始解决方案,say seq-range-gist (0,1 ... Inf)[^10]显示:

\n\n
0 => 0\n1 => 1\n2 => 2\n...\n8 => 8\n9 => 9\n
Run Code Online (Sandbox Code Playgroud)\n\n

接下来,我们希望能够“从打印输出中仅删除第一个元素......”。不幸的say seq-range-gist (0,1 ... Inf)[1..9]是显示:

\n\n
0 => 1\n1 => 2\n2 => 3\n...\n7 => 8\n8 => 9\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们希望左侧的数字=>保留原始序列的编号。为了实现这一点,我们将基础序列从我们想要提取的范围中分离出来。我们添加第二个参数/参数@range,并附加到[@range]子文件的第二行:

\n\n
sub seq-range-gist ( @seq, @range ) {\n  my @pairs = @seq.pairs[@range];\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我们可以编写say seq-range-gist (0,1 ... Inf), 1..9显示:

\n\n
1 => 1\n2 => 2\n3 => 3\n...\n8 => 8\n9 => 9\n
Run Code Online (Sandbox Code Playgroud)\n\n

在您的问题中,您使用的是格式aINDEX = VALUE而不是INDEX => VALUE. 为了允许自定义要点,我们添加第三个&gist例程参数/参数并调用它而不是内置.gist方法:

\n\n
sub seq-range-gist ( @seq, @range, :&gist ) {\n  my @pairs = @seq.pairs[@range];\n  join "\\n", @pairs.head(3)\xc2\xbb.&gist, \'...\', @pairs.tail(2)\xc2\xbb.&gist\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意 sub 主体中的“方法”调用seq-range-gist现在是.&gist,而不是.gist。该语法.&foo调用sub &foo(通常通过只编写 来调用foo),将 the 左侧的调用者.作为 a传递$_参数传递给 sub。

\n\n

另请注意,我已&gist通过在参数前面添加一个命名参数来将其命名为:.

\n\n

所以现在say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }显示:

\n\n
a1 =  1\na2 =  2\na3 =  3\n...\na8 =  8\na9 =  9\n
Run Code Online (Sandbox Code Playgroud)\n\n

添加抛光剂

\n\n

对于关心润色的读者来说,这个答案的其余部分是额外的材料。

\n\n

say seq-range-gist (0, 1, 2, 3), ^3显示:

\n\n
0 => 0\n1 => 1\n2 => 2\n...\n1 => 1\n2 => 2\n
Run Code Online (Sandbox Code Playgroud)\n\n

哎呀。即使有比头和尾加起来更多的对,所以至少我们没有得到重复的行,使用head, ..., tail仅删除一两个元素的方法仍然是没有意义的。让我们更改子正文中的最后一条语句以消除这些问题:

\n\n
  join "\\n",\n    @pairs < $head + $tail + 3   # Of course, the 3 is a bit arbitrary\n      ?? @pairs\xc2\xbb.&gist\n      !! (@pairs.head($head)\xc2\xbb.&gist, \'...\', @pairs.tail($tail)\xc2\xbb.&gist)\n
Run Code Online (Sandbox Code Playgroud)\n\n

接下来,如果在没有范围或要点的情况下调用该子函数,可以做一些有用的事情,那就太好了。我们可以通过给出@range和来解决这个问题&gist参数提供合适的默认值来解决这个问题:

\n\n
sub seq-range-gist (\n  @seq,\n  @range = @seq.is-lazy ?? ^100 !! ^@seq,\n  :&gist = { .gist }\n) {\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果@seq不是偷懒 ,那么默认@range是全范围的@seq。如果@seq无限的(在这种情况下它也是惰性的),那么默认值最多 100就可以了。但是,如果@seq是惰性的但生成的定义值少于 100 个怎么办?为了涵盖这种情况,我们附加.grep: *.value.defined@pairs声明中:

\n\n
  my @pairs = @seq.pairs[@range].grep: *.value.defined;\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一个简单的改进是可选的头部和尾部参数,从而形成最终的完善解决方案:

\n\n
sub seq-range-gist (\n  @seq,\n  @range = @seq.is-lazy ?? ^100 !! ^@seq,\n  :$head = 3,\n  :$tail = 2,\n  :&gist = { .gist }\n) {\n  my @pairs = @seq.pairs[@range].grep: *.value.defined;\n  join "\\n",\n    @pairs <= $head + $tail + 2\n      ?? @pairs\xc2\xbb.&gist\n      !! (@pairs.head($head)\xc2\xbb.&gist, \'...\', @pairs.tail($tail)\xc2\xbb.&gist)\n}\n
Run Code Online (Sandbox Code Playgroud)\n