我应该在 Perl 6 中使用序列还是范围来计数?

Should I count up in Perl 6 with a sequence or a range?

Perl 6 有 lazy lists, but it also has unbounded Range 个对象。你应该选择哪一个来计算整数?

并且有两个点的无限 Range:

0 .. *

有三个点的Seq (sequence)

0 ... *

A Range 使用自然顺序生成连续事物的列表。它继承自 Iterable, but also Positional,因此您可以索引一个范围。您可以检查 Range 中是否有内容,但这不是任务的一部分。

A Seq 可以生成任何你喜欢的东西,只要它知道如何到达下一个元素。它继承自 Iterable, but also PositionalBindFailover,后者通过缓存和列表转换伪造 Positional 内容。如果您只是从一个元素移动到下一个元素,我认为这没什么大不了的。

我要来回讨论这个问题。目前我认为是 Range.

“..”(Range)和“...”(Seq)有区别:

$ perl6
> 1..10
1..10
> 1...10
(1 2 3 4 5 6 7 8 9 10)
> 2,4...10
(2 4 6 8 10)
> (3,6...*)[^5]
(3 6 9 12 15)

“...”运算符可以凭直觉判断模式!

https://docs.perl6.org/language/operators#index-entry-..._operators

据我了解,您只能遍历一个 Seq 一次。它适用于您不需要返回的流式传输(例如,文件)。我认为 Range 应该是一个不错的选择。

0 .. *0 ... * 都可以。

  • 迭代它们,例如使用 for 循环,在这两种情况下具有完全相同的效果。 (两者都不会通过保留已经迭代的元素来泄漏内存。)
  • 将它们分配给一个 @ 变量会产生相同的惰性数组。

因此,只要您只想以 1 为步长将数字累加到无穷大,我认为两者都没有缺点。

... 序列构造运算符更通用,因为它也可以用于

  • 用不同的步骤计数 (1, 3 ... *)
  • 倒数 (10 ... -Inf)
  • 遵循几何序列 (2, 4, 8 ... *)
  • 遵循自定义迭代公式 (1, 1, *+* ... *)

所以当我需要做类似的事情时,为了保持一致性,我会考虑对任何附近和相关的 "count up by one" 使用 ...

另一方面:

  • A Range 可以高效地索引,而不必生成和缓存所有前面的元素,因此如果除了迭代它之外还想索引计数器,这是更可取的。处理元素位置的其他列表操作也是如此,例如 reverseRange 对它们具有高效的重载,而在 Seq 上使用它们必须首先迭代并缓存其元素。
  • 如果你想向上计数到可变终点(如 1 .. $n),使用 Range 更安全,因为你可以确定它永远不会向下计数,不不管 $n 是什么。 (如果端点小于起点,如 1 .. 0,迭代时它将表现为一个空序列,这在实践中往往会得到正确的边缘情况。)
    相反,如果你想安全地向下计数确保它永远不会意外地向上计数,你可以使用 reverse 1 .. $n.
  • 最后,Range 是 "numbers from x to y" 概念的更 specific/high-level 表示,而 Seq 表示 "a sequence of values" 更通用的概念.通常,Seq 由任意生成器代码驱动(参见 gather/take)- ... 运算符只是用于创建一些常见类型序列的语义糖。因此,当 "numbers from x to y" 是您想要表达的概念时,使用 Range 可能会让人感觉更具声明性。但我想这纯粹是心理问题... :P

从语义上讲,一个Range是一个静态的东西(一组有界值),一个Seq是一个动态的东西(一个值生成器)和一个惰性的List一个动态事物的静态视图(生成值的不可变缓存)。

经验法则: 静态优于动态,简单优于复杂。

另外,Seq是可迭代的东西,List是可迭代的位置的东西,Range是有序的可迭代的位置的东西。

经验法则: 根据上下文选择最通用或最具体的。

因为我们只处理迭代并且对位置访问或边界不感兴趣,所以使用 Seq(本质上是一个盒装的 Iterator)似乎是一个自然的选择。但是,有序的连续整数集 恰好 整数 Range 所代表的内容,就我个人而言,这就是我认为最适合您的特定用例的内容。

当没有明确的选择时,我倾向于选择范围,因为它们的简单性(并尽量避免重量级的懒惰列表)。

请注意,语言语法也会将您推向 Range 的方向,这些语法是相当严重的霍夫曼编码(两个字符中缀 ..,一个字符前缀 ^ ).