Welcome to the next issues if *The Pearls of Raku*! Today, some interesting findings that I discovered while reviewing the previous weeks of The Perl Weekly Challenge and a thing that I used for the first ever time when I added a new graph to The Coronavirus Observer.

## unit sub MAIN

The `unit sub MAIN`

construct makes the rest of the file the body of the `MAIN`

function. In other words, it gives a handy way to **declare parameters of your program** and to restrict its values.

Imagine a command-line calculator that you run as:

$ ./calc.raku 42 + 5

You want to make sure that the first and the third arguments are integers, and there is a sign of the operation in between.

Here is a possible solution in Raku (maybe a bit exaggerated just for the sake of demonstration).

my Int $a = +@*ARGS.shift; subset OpStr of Str where /<[-+*/]>/; my OpStr $op = @*ARGS.shift; my Int $b = +@*ARGS.shift;say (given $op { when '+' {$a + $b} when '-' {$a - $b} when '*' {$a * $b} when '/' {$a / $b} })

The highlighted part is where you get the arguments and indirectly validate them.

If you convert the code to a function, you can use function’s signature to check the arguments for you. In the case of a simple script with the only function, use `unit sub MAIN`

:

unit sub MAIN(Int $a, Str $op where /<[-+*/]>/, Int $b); say (given $op { when '+' {$a + $b} when '-' {$a - $b} when '*' {$a * $b} when '/' {$a / $b} })

Also notice the difference in error reporting between these two programs. In the first case, an exception happens:

$ raku calc1.raku 42 plus 3 Type check failed in assignment to $op; expected OpStr but got Str ("plus") in block <unit> at calc1.raku line 3

In the second case, you get a usage message:

$ raku calc2.raku 42 plus 3 Usage: calc2.raku <a> <op> <b>

P. S. Note that you can only use the trick with `MAIN`

. For other functions, you get an error:

A unit-scoped sub definition is not allowed except on a MAIN sub; Please use the block form. If you did not mean to declare a unit-scoped sub, perhaps you accidentally placed a semicolon after routine's definition?

## round

An interesting thing you may skip in the documentation is that the `round`

routine takes an optional `scale`

parameter. You can use it to set the number of digits after the decimal point, for example.

Round the value of π:

say pi.round; # 3

Now, print one, two, or three digits after the decimal point:

say pi.round(0.1); # 3.1

say pi.round(0.01); # 3.14

say pi.round(0.001); # 3.142

But that’s not all! Do you want to get only an odd number as a result? Round the value to a multiple of 2:

say pi.round(2); # 4

Set the scale to 5 or 10 and round it to a number which is a multiple of these numbers:

say pi.round(5); # 5 say pi.round(10); # 0

You can work with big non-round numbers too. Say, let’s round the World population to see billions only:

my $population = 7_802_279_546; say $population.round(1_000_000_000); # 8000000000

And that’s it for now. You can find the source codes of this issue on GitHub.