I want to be able to pass my script the path to a .rakumod file, say <blah>/Mod.rakumod, and be able to access the symbol table as a hash as if I'd used the module instead:
The module:
$ cat Mod.rakumod
unit module Mod;
sub bag is export { ... }
use lib <dir-containing-Mod>
use Mod;
say Mod::EXPORT::.keys
works, as expected, returning (ALL DEFAULT).
On the other hand:
use lib <dir-containing-Mod>
require Mod;
say Mod::EXPORT::.keys
fails with
Could not find symbol '&EXPORT' in 'Mod'
in block <unit> at <blah>
This is despite the fact that even with require, say Mod::.keys does see EXPORT:
use lib <dir-containing-Mod>
require Mod;
say Mod::.keys
---
(EXPORT Mod)
I need to use require to make this dynamic, as I don't know which module I'll want.
I can actually think of one thing to do, but it is absolutely disgusting:
- save my module name into a variable
$mod - have my script write another script
using that module:
my $mod = <whatever>
my $cd = qq:to/END/;
use v6;
use lib qq\|\$\*CWD\|;
use $mod;
say {$mod}::EXPORT::ALL::.keys;
END
'aux.p6'.IO.spurt($cd);
- and then have the initial script call the auxiliary one:
shell("raku aux.p6")
What worked, per raiph's answer (which I've accepted and am here paraphrasing):
- pass the path to the module and save it as
$path; use libthe relevant directory:
my $dir = $path.IO.dirname;
use lib $dir;
- extract the plain file name:
my $modFile = S/(.*)\..*/$0/ with $path.IO.basename;
- finally,
requirethat and pull the.WHOtrick from raiph's answer, slightly adapted:
require ::($modFile);
say ::("{$modFile}::EXPORT::ALL").WHO.keys;
Run with <script> <path> that returned (&bag) all right.
Actually, the above doesn't quite work: use lib $dir will fail saying $dir is empty, because use lib isn't dynamic.
So instead I am now resorting to the unappealing solution of
- copying the module file to a temporary directory
./TMP - having called
use './TMP'; - and then removing that directory when done.