Wiki: Raku

Some external Raku golf tips

The sequence operator (...)

This is one of the more powerful tools in Raku, especially for the numerous sequence holes. The general formation is:

$initialisation,&generator...&endpoint
0,1,*+*...*>32  # Fibonacci

These can be mix and matched. If you leave out the initialisation, if the code uses $_, it will take the value of that variable for the first iteration from the outer scope (defaulting to (Any) if you're in the base program). If you leave out the generator, it will try to interpolate the sequence from the initial list, otherwise just incrementing the last value. Using * as the termination will make it loop forever (if you want until the value is falsey, you'll have to do ?*).

{$_+1}...10    # (Any) turns into a 0, so this is the range 1 to 10. Note that you can't use *+1
0,2...10       # Even numbers from 0 to 10
1...*          # Infinite range

If a range is assigned to a variable or returned, it will probably stay lazy. If you have it as a base statement, it will be evaluated.

Rather than generate a sequence and then print the values, you can print the values inside either the generator or the termination, as both are executed for each element.

(0,1,*+*...*>32)>>.say;
0,1,{say $^a;$a+$^b}...*>32;
0,1,*+*...{.say;$_>32};
0,1,*+*...*.say+*>35;

Lambda/Blocks

The generator is a function, which can either be block {} or a Whatever lambda. Both of these can take multiple previous elements (as shown above in the Fibonacci example), but the block can also take a list of all the previous elements as @_ (this is mutually exclusive with $_), or no input at all. Also note that $ variables will persist in each block as usual, which can let you keep track of the length of the list, or some persistant value.

{@_.sum+@_}...*   # 2**n-1
{2**$++-1}...*
{2**@_-1}...*
0,2* *+1...*

Termination

Termination is interesting. Mechanically, it functions like the smartmatch operator (~~), which calls the ACCEPTS method, which has some interesting interactions. This means you can use:

1...&say&100;            # Print 1 to 100
1...{$_%2}&:say&99;      # Print odds from 1 to 99
1...*%2&:say&99;         # Doesn't work, * swallows surroundings
1...&(*%2)&:say&99;      # Instead do this 

Example Templates

Most sequence holes involve either filtering from 0 to n, or some transformation of previous elements, so a good start is to use one of these templates:

0...&cond&:say&n
1,&gen...&say&n
1,{.say;code}...n
1,&gen...*.say+*>n
1,&gen...&say^ ^n

Remember to be creative with termination conditions, as well as where you put the printing section of the code.