🎄 9/25. 关于 X 的更多东西, Raku 中的 .. 和 …
— 焉知非鱼欢迎来到 Raku One-Liner Advent Calendar 的第9天! 在第6天,我们有一个带有交叉算子的构造,(999...100) X* (999...100)
。 今天,我们将从11月开始进入类似的结构:
1..10 X* 1..10
它打印乘积表的项,数字从1到10:
(1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100)
关于这样的结构,有几点需要了解。
您可能已经注意到 999 ... 100
和 1..10
之间存在两个细微差别。 在一种情况下,有三个点,另一个只有两个点。 在第一种情况下,边界在递减数字,在第二种情况下,是递增数字。
Raku 中的两个点是范围运算符。 它创建一个 Range
,或者换句话说,创建 Range 类型的对象。
Raku 中的三个点是序列运算符。 在我们的示例中,它创建序列或 Seq 类型的对象。
您始终可以通过在对象上调用 WHAT 方法来检查类型(REPL会话的片段如下所示):
> (1..10).WHAT
(Range)
> (1...10).WHAT
(Seq)
查看 Rakudo 的源代码也很有趣,看看 Range
和 Seq
有哪些属性。
my class Range is Cool does Iterable does Positional {
has $.min;
has $.max;
has int $!excludes-min;
has int $!excludes-max;
has int $!infinite;
has int $!is-int;
. . .
}
my class Seq is Cool does Iterable does Sequence {
has Iterator $!iter;
. . .
}
在 Range
对象中,有最小值和最大值,而在 Seq
中我们看到一个迭代器。
在某些情况下,例如,在一个简单的循环中,您可以在范围或序列之间进行选择:
.say for 1..10;
.say for 1...10;
但如果你想倒数,范围将不起作用:
> .say for 10..1;
Nil
使用序列就没问题:
> .print for 10...1;
10987654321>
在开始感觉良好之前,使用范围和序列是明智的。 将它们保存在变量中,在操作中使用,使用 say
或 dd
打印。
作为一个起点,考虑以下三个操作:
(1, 2, 3) X* (4, 5, 6);
(1..3) X* (4..6);
(1...3) X* (4...6);
这就是你明天的 Advent 之前你可以做的事情!