Technology Aug 30, 2026 · 3 min read

Raku: a language that counts to infinity (Part 2)

In this part, let's look at infinite sequences from another angle: let's start collecting the values. First of all, Raku has a pair of built-in routines gather and take. They are useful when you need to collect data that's computed along the way. For example: my @data = gather { for ^50 {...

DE
DEV Community
by Andrew Shitov
Raku: a language that counts to infinity (Part 2)

In this part, let's look at infinite sequences from another angle: let's start collecting the values.

First of all, Raku has a pair of built-in routines gather and take. They are useful when you need to collect data that's computed along the way. For example:

my @data = gather {
    for ^50 {
        my $value = 100.rand.Int;
        take $value if 45 < $value < 55;
    }
}

say @data;

The program prints a few random numbers between 45 and 55 (or none when unlucky). You don't know upfront how many numbers it will pick, but at least there's some limit: the loop body runs only 50 times, and the random numbers are less than 100.

So, it's time to introduce some infinity into the code. The next program scans the number, but does not explicitly say how many of them the user will use later. The second line, for example, demands the first five items, and that's when the real computation happens:

my $data = gather for 1 .. ∞ { take $_ if 45 < $_ < 55 }
say $data[^5]; # (46 47 48 49 50)

Surprisingly, working with infinities makes the code clearer for the reader. You just describe what to do with data, but omit the length. The next snippet literally says “Convert the numbers to their squares”. You apply this rule to the infinite (but lazy) range 1 .. ∞, and only then you take the first five elements.

say (gather for 1 .. ∞ { take $_ × $_ }).head(5);

Once again, note that you first apply the action to an infinite sequence, and only then cut it to the size you need. Not vice versa (of course you can if you know when to stop; but sometimes you need the condition on the results rather than on the source). The program prints:

(1 4 9 16 25)

A similar approach is demonstrated in the next two lines:

say ([\+] 1 .. ∞)[^10];
say ([\*] 1 .. ∞)[^7];

Wait, how? Add up or multiply all the integer numbers, and then take the first few elements of one of the triangle metaoperator's results?!

Yes, no problem. A couple of triangle metaoperators are only used to compute the values for the first few items, not for the whole infinity:

(1 3 6 10 15 21 28 36 45 55)
(1 2 6 24 120 720 5040)

Here is a slightly more complex program, but the principle is the same, you define a rule and allow it work for any number of items:

my @pascal = [1], -> @p { [0, |@p Z+ |@p, 0] } ... ∞;
.say for @pascal[^5];

The function in this case is an anonymous pointy block -> @p { [0, |@p Z+ |@p, 0] }. The program prints five rows of Pascal's triangle:

[1]
[1 1]
[1 2 1]
[1 3 3 1]
[1 4 6 4 1]

By the way, you can also ask Raku to add up everything in 1 .. ∞ and you'll get the correct answer: Inf.

say [+] 1 .. ∞;

Again and again we can see that things like Inf and are not black holes in Raku. They behave according to the task you are working on.

say <a b c> Z (1 .. ∞);

Even though one of the operands of Z is an infinite range, the result is limited to the first three items, as the left operand is quite measurable:

((a 1) (b 2) (c 3))

But nobody can stop us from having infinite ranges on both sides of Z and even making some computations on those as we did earlier. Just make sure you do not take too many:

say ((1 .. ∞) Z (1 .. ∞).map(* ** 2)).head(4);

This program prints the numbers with their squares:

((1 1) (2 4) (3 9) (4 16))

If you are curious why, remove the map and confirm that this weird construct just gives you the same number twice:

((1 1) (2 2) (3 3) (4 4))

As homework, rewrite the last example without using the Z metaoperator.

DE
Source

This article was originally published by DEV Community and written by Andrew Shitov.

Read original article on DEV Community
Back to Discover

Reading List