I am updating a raku module (Physics::Measure)
My old code looks like this:
unit module Physics::Measure ...
class Length is Measure is export {}
class Mass is Measure is export {}
class Current is Measure is export {}
...
On the client side, we go:
use Physics::Measure;
say my Length $b = 15m; #15m
To handle localisation, I would like to declare and export these classes programatically, something like:
my @names = <Length Mass Current>;
for @names -> $name {
class ::($name) is Measure is export {}
}
This gives the error Name ::($name) is not compile-time known, and can not serve as a package name.
Okaay, so maybe (from the docs) I can go something like:
my package EXPORT::DEFAULT {
for @names -> $name {
OUR::($name) := $name;
}
}
-or maybe, with a for loop tbd-
sub EXPORT {
Map.new:
($name => Length is Measure)
}
Please can someone provide a steer on the best way to (i) dynamically declare the classes and (ii) then to export them???
The secret is really in the notion the names of the classes shouldn't be dynamic, but the names with which they are exported should be dynamic:
# file lib/Physics/Measure.rakumod
class Length {}
class Mass {}
class Current {}
sub EXPORT(*@names) {
Map.new( @names.map: -> $from, $to { $to => ::($from) } )
}
This would allow you to specify orginal name -> wanted name pairs as such:
$ raku -Ilib -e 'use Physics::Measure <Length Foo Current Bar>; dd Foo, Bar'
Length
Current
This is the basic mechanism for handling any non-named arguments in a use
statement. Using named arguments is currently handled by the default handler, and that sadly currently not possible. A much more natural interface would have been :Length<Foo>, :Current<Bar>
.