What is the proper way to load Raku modules using rakudo-star?
Asked Answered
W

2

8

I have the following project

$ tree
.
├── lib
│   └── MyModule.raku
└── main.raku

$ cat lib/MyModule.raku
use v6;
unit module MyModule;
sub hello { say 'hello' }

$ cat lib/main.raku
use v6;
use MyModule;
MyModule.hello();

I would like to run main.raku using the latest rakudo-star image. However the following occurs

$ docker run -i --rm -u $(id -u) \
--workdir /work \
--volume  $PWD:/work \
--entrypoint bash \
rakudo-star perl6 -I ./lib main.raku
===SORRY!===
Could not find MyModule at line 3 in:
    file#/work/lib
    inst#/.perl6
    inst#/usr/share/perl6/site
    inst#/usr/share/perl6/vendor
    inst#/usr/share/perl6
    ap#
    nqp#
    perl5#

I have also tried inserting use lib '/work/lib' before use MyModule in main.raku with the same result.

Walczak answered 5/3, 2020 at 1:59 Comment(1)
The way you show it here, main.raku is not in lib, right?Become
D
5

There are several problems.

  1. Modules don't end with .raku. They end with .rakumod or .pm6 (for now).
    (Technically after you install, it doesn't actually matter what the extension is as long as you have it properly declared in META6.json.)

  2. Subroutines are lexically scoped by default (my), and are also not exported by default.
    So there is no way to access hello() outside of the module it is defined in.

  3. Modules don't have methods, so you can't call hello as a method.
    Even if they did have methods they wouldn't start with the sub keyword.


You can globally scope the subroutine with our:

lib/MyModule.rakumod

use v6.d;
unit module MyModule;

our sub hello () { say 'hello' }
#^
# \
#  globally scoped

main.raku

use v6.d;
# use lib './lib';
use module MyModule;

MyModule::hello();
#       ^^
#        \
#         namespace delimiter

You could export it instead:

lib/MyModule.rakumod

use v6.d;
unit MyModule;

#             mark for export
#            v-------v
sub hello () is export {
    say 'hello'
}

main.raku

use v6.d;
# use lib './lib';
use MyModule;

hello();

In addition to is export, there are other more fine grained ways to export.

I would recommend that if you are going to export, that you also make it global with our. That way if someone uses your module, but doesn't want to import your subs; they still have access to them.

Designing answered 7/3, 2020 at 0:11 Comment(1)
Thank you, my syntax/grammar was totally screwed up, but I wasn't even worrying about until I could get the module to to import. Thank you for the thorough answer 😃Walczak
S
5

New Raku versions uses the .rakumod as file extension for modules. The older .pm6 extension is still supported. More information regarding the new file extensions can be found in the Path-to-Raku ticket. More information about modules is available in the raku documentation.

Sd answered 5/3, 2020 at 5:8 Comment(5)
Changing the filename does not appear make any difference.Walczak
Exact the same error message? After change to MyModule.rakumod I get the following message No such method 'hello' for invocant of type 'MyModule'..Sd
Exact same, unfortunately 😦Walczak
Hmm, can you try to use .pm6 as module file extension?Sd
That one worked! And by worked I mean gave me a different error, but that means the module was imported 😃 Is there any documentation related to this?Walczak
D
5

There are several problems.

  1. Modules don't end with .raku. They end with .rakumod or .pm6 (for now).
    (Technically after you install, it doesn't actually matter what the extension is as long as you have it properly declared in META6.json.)

  2. Subroutines are lexically scoped by default (my), and are also not exported by default.
    So there is no way to access hello() outside of the module it is defined in.

  3. Modules don't have methods, so you can't call hello as a method.
    Even if they did have methods they wouldn't start with the sub keyword.


You can globally scope the subroutine with our:

lib/MyModule.rakumod

use v6.d;
unit module MyModule;

our sub hello () { say 'hello' }
#^
# \
#  globally scoped

main.raku

use v6.d;
# use lib './lib';
use module MyModule;

MyModule::hello();
#       ^^
#        \
#         namespace delimiter

You could export it instead:

lib/MyModule.rakumod

use v6.d;
unit MyModule;

#             mark for export
#            v-------v
sub hello () is export {
    say 'hello'
}

main.raku

use v6.d;
# use lib './lib';
use MyModule;

hello();

In addition to is export, there are other more fine grained ways to export.

I would recommend that if you are going to export, that you also make it global with our. That way if someone uses your module, but doesn't want to import your subs; they still have access to them.

Designing answered 7/3, 2020 at 0:11 Comment(1)
Thank you, my syntax/grammar was totally screwed up, but I wasn't even worrying about until I could get the module to to import. Thank you for the thorough answer 😃Walczak

© 2022 - 2024 — McMap. All rights reserved.