In this issue, I will be looking at the three use cases with the where
clause. All the examples refer to the MAIN
function, but the content is applicable to any other function.
More than one parameter
If the function takes more than one parameter and you want to enforce some restrictions on the values, you do not have to create separate where
clauses for each of the parameters.
For example, check if the two arguments of the MAIN
function are within the given limits:
sub MAIN(Int $a where 10 < * <= 20, Int $b where * > 20) { say "OK: $a $b"; }
Here, each parameter has its own where
clause. It is also possible to have a single where
clause, especially when the values of the two parameters are connected.
sub MAIN(Int $a, Int $b where 10 < $a < $b > 20) { say "OK: $a $b"; }
Check the file
If you are passing the name of a file, you can check for its existence directly in the where
clause! Look at the example:
sub MAIN(Str $filename where *.IO.f) { say "$filename exists"; }
If the files does not exist, the function (or the whole program in the case of the MAIN
function) will not even be called.
Informative where
When you have the where
clause in the MAIN
function, and the arguments do not pass the checks, the compiler prints a default prompt listing the options to run the program. Consider the example:
sub MAIN(Int $x where $x < 10) { say "x = $x"; }
If you run the program with no arguments, you get the message:
$ raku where-int.raku Usage: where-int.raku <x>
This is good so far. But if you supply an integer which is incorrect, you get the same message:
$ raku where-int.raku 20 Usage: where-int.raku <x>
No information as to why it is not accepted.
One of the possible solutions is to add a special comment (a declarator block):
sub MAIN(Int $x where $x < 10 #= $x must be < 10 ) { say "x = $x"; }
Now, the message is printed together with the usage message:
$ raku where-int.raku 20 Usage: where-int.raku <x> -- $x must be < 10
The second option is to use die
directly in the where
block:
sub MAIN( Int $x where { $x < 10 or die "Invalid \$x. Got $x but must be < 10." }) { say "x = $x"; }
Now, we are able to prepare an even more informative message:
$ raku where-print.raku 20 Invalid $x. Got 20 but must be < 10. in sub MAIN at where-print.raku line 1 in block <unit> at where-print.raku line 1
* * *
Find the code of this issue on GitHub and browse for more Raku Pearls.