如何在 Raku 中无限期和懒惰地循环列表?

how to cycle through list indefinitely and lazily in Raku?

这主要是为了了解 Raku 有多棒。

问题

是否有内置方法可以获取一个列表并无限循环它,从而生成惰性列表

a, b, c, a, b, c, ...

(a, b, c)documentation 列表中的任何内容似乎都无法解决问题。

可能的解决方案

我至少能想到几个。

更沉闷的脚踏实地的方法是 map @array[<variable> mod length-of-@array] 在惰性范围 0..Inf 上。在 perl6 REPL 中:

> my @ar=<a b c>
[a b c]
> (0..Inf).map({ @ar[$_ % @ar.elems] }).[0..100]
(a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a ...)

一个更酷的(我认为)解决方案是让你首先将你的列表变成 slip, and then apply the repetition operator 无限期地到那个滑动:

> my @ar=<a b c>
[a b c]
> (|@ar xx *).[0..100]
(a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a ...)

结论

尽管我可以做到这一点(尤其是最后一个解决方案非常简洁和令人满意),但我想知道我是否遗漏了专门为此目的而内置的任何东西。


编辑回复:接受的答案

这是对@Brad Gilbert 的回答稍加阐述。 «~» 运算符包装 string concatenation ~ in the « » hyper operator,这导致将包装的二元运算符应用于从两个列表中按顺序选择的元素。

所以为了实现我想要的(列表循环到所需的长度,比如 100),一个人会做

<a b c> <<~>> ("" xx 100)

这会产生

(a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a b c a)

(100 个条目)。它确实有一些缺点:

<a b c> <<~>> ("" xx *)

returns

List on right side of hyperop of infix:<~> is known to be infinite
  in block <unit> at <unknown file> line 1

既然能写这么短,为什么还要加个功能。特别是因为它可能是一个罕见的事件,你会需要这样的东西。

|< a b c > xx *

有一个例外,如果您使用 «~» 之类的东西,它会为您扩展。

< a b c > «~» (1..10)
# (a1 b2 c3 a4 b5 c6 a7 b8 c9 a10)

你的第一个“down-to-earth”例子可以写成(^Inf).map({ @ar[$_ % *] })

此外,滑动和重复效果很好,但仅适用于合理大小的列表。

sub bad-cycle(@xs) {
    |@xs xx Inf
}

my $big-list = ^1e6;
say bad-cycle($big-list).head(100);    # Hangs for several seconds

更好的选择是如上所示的地图,或像这样的 gather 循环

sub cycle(@xs) {
    gather loop { .take for @xs }
}

say cycle($big-list).head(100);    # Instant output

不知道我有没有看懂问题。但据我了解,您需要一种方法来按照模式生成无限列表。好吧,如果这是问题所在 在书“Think in Raku”中,第 14.5 部分(改编自如何做斐波那契数列)

("a","b","c", -> $a, $b, $c {$a} ...* )

这个元素是 pure-list,如果你想要提取值,你需要列表上更常规的东西(比如分配和提取值)

my @list = ("a","b","c", -> $a, $b, $c {$a} ...* )
@list[0..100]
@list[91]

我认为在 Inf 上下文中使用 map 不是个好主意,但如果我遗漏了什么请告诉我,我也在学习这门很棒的语言!!