Python’s itertools package is the gold standard for working with iterable streams of data.

It always irked me that Python needed an entire package to do things that I felt like the base language should easily support. I know Raku treats lazy lists as first class objects, so that made me start to wonder: how well does Raku stack up?

To answer this question, I’m just going to go through every function in the itertools and provide a one liner Raku equivalent. These will all work with normal iterables as well as infinite lists and sequences. Let’s begin:

count():

-> $start, $end = * { $start ... $end }

cycle():

-> @p { lazy gather { loop { for @p -> $p { take $p } } } }

From CIAvash on the Raku IRC:

-> @p { |@p xx * }

repeat():

-> $elem, $n = * { $elem xx $n }

accumulate():

-> @p, &func = * + * { [\[&func]] @p }

chain() / chain.from_iterable():

This is the default behavior of slurpy arguments.

-> *@p { @p }

compress():

-> @d, @s { flat @d Zxx @s }

dropwhile():

-> &pred, @seq { lazy gather for @seq { take $_ if &pred ff * } }

filterfalse():

This is a builtin: the grep method, using a none Junction.


groupby():

This is a builtin: the categorize method or the classify method.


islice():

This is a builtin: basic positional list slices are capable of this.


starmap():

-> &func, @seq { @seq>>.&{ func(|$_) } }

takewhile():

I could write this the same as dropwhile() but just break out of the for loop early, but I’m gonna take full advantage of the sequence operator here instead.

-> &pred, @seq { |@seq ...^ { !pred($_) } }

tee():

Not really sure that this one makes sense to implement, as we’re technically working with lazy lists for the most part here and not generated sequences.

For that matter, Seq does provide a builtin, the cache method, that may be used effectively the same way in practice.


zip_longest():

Probably the hardest one to implement. Nothing in Raku really naturally does this operation. Without accounting for length, and stopping at the shortest list, it would simply be:

-> **@p { [Z] @p }

Going to think about this one overnight, actually. I feel like there’s an elegant way to do this really quickly but I can’t put my finger on it. Pester me using the links down below if I haven’t filled this one in yet.


product():

-> +p { [X] p }

permutations():

This is a builtin: the permutations method.


combinations():

This is a builtin: the combinations method.


combinations_with_replacement():

-> @p, $r { |@p.combinations($r), |([Z] @p xx $r) }

Well, that’s about all of them. Every itertools function written on one page, in Raku one liners. This is all just food for thought: there really is no reason for Python to be as verbose and yet so lacking in features, and I suppose this is some sort of proof.

Message me using the contact info below, if you’d like.