This is mostly to geek out on how awesome Raku is.
Question
Are there built-in methods that will take a list and cycle through it indefinitely, producing, say, the lazy list
a, b, c, a, b, c, ...
out of (a, b, c)
? Nothing in the documentation on lists seems to obviously do the trick.
Possible solutions
I can think of at least a couple.
The more plodding down-to-earth method would be to map @array[<variable> mod length-of-@array]
over the lazy range 0..Inf
. In the 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 ...)
A cooler (I think) solution would have you first turn your list into a slip, and then apply the repetition operator to that slip indefinitely:
> 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 ...)
Conclusion
Even though I can achieve this (and the last solution in particular is very pithy and satisfying), what I am wondering is whether I'm missing anything built in specifically for this purpose.
Edit Re: the accepted answer
This is to elaborate slightly on the answer by @Brad Gilbert. The «~»
operator wraps string concatenation ~
in the « »
hyper operator, which results in applying the wrapped binary operator to elements selected sequentially from the two lists.
So to achieve what I wanted (list-cycling to a desired length, like say 100), one would do
<a b c> <<~>> ("" xx 100)
This produces
(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 entries). It does have a couple of drawbacks though:
- it coerces the list entries to strings, due to the application of
~
- it doesn't actually produce a lazy infinite list:
<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
When it can be written this short, why add a feature just for that. Especially since it is probably a rare event that you would need such a thing.
Well there is one exception, if you use something like
«~»
it extend it out for you.