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.
Alternatively, there is a Getopt::Long for perl6 too. Your program works in it with almost no modifications:
use Getopt::Long;
my $data = "file.dat";
my $length = 24;
my $verbose;
get-options("length=i" => $length, # numeric
"file=s" => $data, # string
"verbose" => $verbose); # flag
say $length;
say $data;
say $verbose;