DEV Community

Juan Julián Merelo Guervós
Juan Julián Merelo Guervós

Posted on • Updated on

Loops in Raku and when to use them

Loops can be single or double edged

Sooner or later you need to keep some state between an element and the next, generate some side effect, work with several data structures or, in general, work in a way that can’t be filtered using grep, mapped or reduced; or simply you need to perform some output during the processing of a data structure, something that can’t be done in the functions seen in the previous section. What you need is a for loop. But let’s talk first where and when you can use them.

Iterator is a role, and, as such and in general, are not intended to be used directly by programmers, but underlie a few, very useful, classes. The basic idea about iterators is that they are lists that can be traveled only once; they are going to be accessed sequentially, starting by the first element, and getting to the last one, which is marked as IterationEnd. The single most important function they have is pull-one, which extracts an element from them. In general, you will be able to iterate over structures that are appropriately called Iterable. Iterable is a role with a few methods, the most important of which is iterator, which converts any data structure in an, of course, Iterator. All that is happening under the hood when you use a for loop.

Let’s see a simple for loop:

  .say for ^3 # 0␤1␤2␤
Enter fullscreen mode Exit fullscreen mode

Where ␤ is a carriage return; that is, they will appear in separate lines. ^3 is a Range. Ranges implement the Iterator role, so what for is doing is actually calling ^3.iterator, which returns an Iterator. Every iteration, for calls pull-one on that iterator, until IterationEnd is reached.

Of course, even if that’s happening under the hood, you can also think that what for does is topicalizing, in turn, every element of the data structure it’s being applied to. And you can also use for in front, but in that case the syntax calls for using a block as the loop body.

 for ^3 { .say } # 0␤1␤2␤
Enter fullscreen mode Exit fullscreen mode

As is shown, this would be exactly the same result as before. We can combine this “doing” loop with a “producing” statement; when you need to create a data structure on the fly, the gather/take statements will do it. Gather will be used as the beginning of the loop, and will have a block inside where every take will produce a new element in a list.

say gather { take "this"; take "that" }  (this that)
Enter fullscreen mode Exit fullscreen mode

This will produce a list with two elements, one for every “take”. That’s not a loop, obviously, although it has got the same use case that loops would have in some other languages. You can use it with a loop, however

say gather { take "Number-$_" for 1..3 } # (Number-1 Number-2 Number-3)
Enter fullscreen mode Exit fullscreen mode

In this case, we are using the topic variable created by the loop, $_, to generate a list of three strings; every time take is used a new string is generated, and they are all reunited in a single structure by gather.

Note: I initially wrote this mini-tutorial for the book "Perl 6 Quick Reference", which I'm writing for was eventually published by APress. However, it didn't fit the rest of the book. It might be useful anyway, so here it is.

Top comments (3)

epsi profile image
E.R. Nurwijayadi

Good article. Thank you for posting.

This Raku approach remind me of generator/yield pattern.

I'm a beginner in Raku. To help more beginner, I have made a working example of this gather take pattern. And then continue to concurrency with channel.


First the data structure

Data Structure: Songs Records in List of Hashes

Then we can bundle the gather-take in a producer function. Raku takes short code to solve this unique challenge.

Gather and Take

I hope this could help other who seeks for other case example.


Thank you for posting with general introduction.

jj profile image
Juan Julián Merelo Guervós

Amazing! Thanks a lot.

kirklewis profile image
Kirk Lewis

Cheers for sharing Juan, this is definitely worth knowing.
Perl 6 continues to surprise me :)