I want to make a modulino (a file that can run as either a module or a script) in Perl6.
The following code "processes" file names from the command line:
sub MAIN ( *@filenames )
{
for @filenames -> $filename
{
say "Processing $filename";
}
}
Saving this as main.pm6
I can run it and it works:
perl6 main.pm6 hello.txt world.txt
Processing 'hello.txt'
Processing 'world.txt'
So, I want this to be a module so that I can add functions and make testing it easier. However, when I add a module
declaration to it, it no longer outputs anything:
module main;
sub MAIN ( *@filenames )
{
for @filenames -> $filename
{
say "Processing '$filename'";
}
}
Which results in nothing output:
perl6 main.pm6 hello.txt world.txt
So, how can I build a modulino in Perl6?
I'm using Perl6 running on MoarVM from the January 2015 release of Rakudo Star.
When I try wrapping the module in braces:
module main
{
sub process (@filenames) is export
{
for @filenames -> $filename
{
say "Processing '$filename'";
}
}
};
sub MAIN ( *@filenames )
{
process(@filenames)
}
I also get errors:
===SORRY!=== Error while compiling main.pm6
Undeclared routine:
process used at line 14. Did you mean 'proceed'?
The MAIN
sub needs to be declared outside the module, but it still must be able to see process
.
There are multiple ways to achieve this, eg by not declaring a module at all
sub process(@filenames) {
for @filenames -> $filename {
say "Processing '$filename'";
}
}
sub MAIN(*@filenames) {
process(@filenames);
}
by making process
our-scoped and calling it by its longname
module main {
our sub process(@filenames) {
for @filenames -> $filename {
say "Processing '$filename'";
}
}
}
sub MAIN(*@filenames) {
main::process(@filenames);
}
or by exporting process
and importing it in the body of MAIN
module main {
sub process(@filenames) is export {
for @filenames -> $filename {
say "Processing '$filename'";
}
}
}
sub MAIN(*@filenames) {
import main;
process(@filenames);
}
In my opinion the most appropriate option is to add MAIN
to the module and import it into the script's mainline. This way, everything declared within the module is visible within MAIN
without having to explicitly export everything:
module main {
sub process(@filenames) {
for @filenames -> $filename {
say "Processing '$filename'";
}
}
sub MAIN(*@filenames) is export(:MAIN) {
process(@filenames);
}
}
import main :MAIN;
Note that this does not export MAIN
by default, ie users of your module will only get it if they provide the :MAIN
tag.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With