我应该用Perl 6计算序列还是范围?

bri*_*foy 10 range perl6 seq raku

Perl 6有懒惰列表,但它也有无界的Range对象.您应该选择哪一个按整数计算?

并且有两个点的无界范围:

0 .. *
Run Code Online (Sandbox Code Playgroud)

有三个点的Seq(序列):

0 ... *
Run Code Online (Sandbox Code Playgroud)

A Range使用它们的自然顺序生成连续的东西列表.它继承自Iterable,但也是Positional,因此您可以索引范围.您可以检查是否有某些内容Range,但这不是任务的一部分.

Seq只要它知道如何到达下一个元素,A 就可以生成你喜欢的任何东西.它继承自Iterable,还有PositionalBindFailover,它Positional通过缓存和列表转换来伪造东西.如果你只是从一个元素转移到另一个元素,我认为这不是什么大问题.

我在这上面来回走动.目前我在想它的范围.

sml*_*mls 10

这两个0 .. *0 ... *的罚款.

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

因此,只要您只想将数字计数到无穷大一步,我就不会看到任何不利因素.

...序列建设运营商是比较通用的,虽然,因为它也可以用来

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

因此,当我需要做类似的事情时,我会考虑使用...附近的任何相关的"按一个数量计算",以保持一致性.

另一方面:

  • A Range可以高效地编制索引,而不必生成和缓存所有前面的元素,因此如果您想要对计数器进行索引以及迭代它,那么这是优选的.对于处理元素位置的其他列表操作也是如此,例如reverse:Range对它们进行有效的重载,而在a Seq上使用它们必须首先迭代并缓存其元素.
  • 如果你想向上计数到一个可变终点(如1 .. $n),那么使用a会更安全,Range因为你可以确定它永远不会向下计数,无论是什么$n.(如果端点小于起始点,如同1 .. 0,则在迭代时它将表现为空序列,这往往会在实践中获得边缘情况.)
    相反,如果您想安全地向下计数,确保它永远不会意外地计数向上,你可以使用reverse 1 .. $n.
  • 最后,a Range是"从x到y的数字"概念的更具体/更高级别的表示,而a Seq表示"一系列值"的更通用的概念.Seq通常,A 由任意生成器代码驱动(参见gather/take) - ...运算符只是创建一些常见类型序列的语义糖.因此,当"从x到y的数字"是您想要表达的概念时,使用范围可能会更具声明性.但我认为这只是一种纯粹的心理问题......:P


Chr*_*oph 8

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

经验法则:首选静态而不是动态,但简单过于复杂.

另外,a Seq是可迭代的东西,a List是可迭代的位置事物,a Range是有序的可迭代位置事物.

经验法则:根据上下文,使用最通用或最具体的.

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

当没有明确的选择时,我倾向于更喜欢范围而不是简单(并试图避免懒惰的列表,重量级).

请注意,语言语法也会向你推动Range,这是相当重要的霍夫曼编码(双字符中缀..,一个字符前缀^).

  • "*迭代总是以Seq的方式发生*" - 我不认为`for 1 ..*{}`曾构造一个`Seq`.根据我的理解,`for`循环1)看到它有一个`Iterable`,2)调用`.iterator`来获得一个`Iterator`,3)继续调用[`.pull-one`](在该迭代器上的https://docs.perl6.org/type/Iterator#method_pull-one),直到它获得`IterationEnd`. (2认同)