Basics
That feature is built into Raku (formerly known as Perl 6). Here is the equivalent of your Getopt::Long
code in Raku:
sub MAIN ( Str :$file = "file.dat"
, Num :$length = Num(24)
, Bool :$verbose = False
)
{
$file.say;
$length.say;
$verbose.say;
}
MAIN
is a special subroutine that automatically parses command line arguments based on its signature.
Str
and Num
provide string and numeric type constraints.
Bool
makes $verbose
a binary flag which is False
if absent or if called as --/verbose
. (The /
in --/foo
is a common Unix command line syntax for setting an argument to False
).
:
prepended to the variables in the subroutine signature makes them named (instead of positional) parameters.
Defaults are provided using $variable =
followed by the default value.
Aliases
If you want single character or other aliases, you can use the :f(:$foo)
syntax.
sub MAIN ( Str :f(:$file) = "file.dat"
, Num :l(:$length) = Num(24)
, Bool :v(:$verbose) = False
)
{
$file.say;
$length.say;
$verbose.say;
}
:x(:$smth)
makes additional alias for --smth
such as short alias -x
in this example. Multiple aliases and fully-named is available too, here is an example: :foo(:x(:bar(:y(:$baz))))
will get you --foo
, -x
, --bar
, -y
and --baz
and if any of them will pass to $baz
.
Positional arguments (and example)
MAIN
can also be used with positional arguments. For example, here is Guess the number (from Rosetta Code). It defaults to a min of 0 and max of 100, but any min and max number could be entered. Using is copy
allows the parameter to be changed within the subroutine:
#!/bin/env perl6
multi MAIN
#= Guessing game (defaults: min=0 and max=100)
{
MAIN(0, 100)
}
multi MAIN ( $max )
#= Guessing game (min defaults to 0)
{
MAIN(0, $max)
}
multi MAIN
#= Guessing game
( $min is copy #= minimum of range of numbers to guess
, $max is copy #= maximum of range of numbers to guess
)
{
#swap min and max if min is lower
if $min > $max { ($min, $max) = ($max, $min) }
say "Think of a number between $min and $max and I'll guess it!";
while $min <= $max {
my $guess = (($max + $min)/2).floor;
given lc prompt "My guess is $guess. Is your number higher, lower or equal (or quit)? (h/l/e/q)" {
when /^e/ { say "I knew it!"; exit }
when /^h/ { $min = $guess + 1 }
when /^l/ { $max = $guess }
when /^q/ { say "quiting"; exit }
default { say "WHAT!?!?!" }
}
}
say "How can your number be both higher and lower than $max?!?!?";
}
Usage message
Also, if your command line arguments don't match a MAIN
signature, you get a useful usage message, by default. Notice how subroutine and parameter comments starting with #=
are smartly incorporated into this usage message:
./guess --help
Usage:
./guess -- Guessing game (defaults: min=0 and max=100)
./guess <max> -- Guessing game (min defaults to 0)
./guess <min> <max> -- Guessing game
<min> minimum of range of numbers to guess
<max> maximum of range of numbers to guess
Here --help
isn't a defined command line parameter, thus triggering this usage message.
See also
See also the 2010, 2014, and 2018 Perl 6 advent calendar posts on MAIN
, the post Parsing command line arguments in Perl 6, and the section of Synopsis 6 about MAIN.