Я обновляю модуль раку (Physics::Measure)
Мой старый код выглядит так:
unit module Physics::Measure ...
class Length is Measure is export {}
class Mass is Measure is export {}
class Current is Measure is export {}
...
На стороне клиента делаем:
use Physics::Measure;
say my Length $b = 15m; #15m
Чтобы справиться с локализацией, я хотел бы объявить и экспортировать эти классы программно, например:
my @names = <Length Mass Current>;
for @names -> $name {
class ::($name) is Measure is export {}
}
Это дает ошибку Name ::($name) is not compile-time known, and can not serve as a package name.
Хорошо, возможно (из документации) я могу сделать что-то вроде:
my package EXPORT::DEFAULT {
for @names -> $name {
OUR::($name) := $name;
}
}
-или, может быть, с циклом for, будет определено позднее-
sub EXPORT {
Map.new:
($name => Length is Measure)
}
Пожалуйста, может ли кто-нибудь подсказать, как лучше всего (i) динамически объявлять классы и (ii) затем экспортировать их???
Секрет на самом деле в том, что имена классов не должны быть динамическими, а имена, с которыми они экспортируются, должны быть динамическими:
# file lib/Physics/Measure.rakumod
class Length {}
class Mass {}
class Current {}
sub EXPORT(*@names) {
Map.new( @names.map: -> $from, $to { $to => ::($from) } )
}
Это позволит вам указать исходное имя -> нужные пары имен как таковые:
$ raku -Ilib -e 'use Physics::Measure <Length Foo Current Bar>; dd Foo, Bar'
Length
Current
Это базовый механизм обработки любых неименованных аргументов в операторе use
. Использование именованных аргументов в настоящее время обрабатывается обработчиком по умолчанию, но, к сожалению, в настоящее время это невозможно. Гораздо более естественным интерфейсом был бы :Length<Foo>, :Current<Bar>
.
Но это только моя точка зрения: нельзя не попасть в страну QAST/RakuAST. Но вы можете переименовать их при импорте в область.
Ах хорошо. Что ж, в этом модуле существует острая потребность в макросах (код мог бы быть намного проще/быстрее, если бы можно было создать экземпляры 227-ми объектов-модулей и хранить их в предварительной компоновке)... но я оставляю это для следующего большого обновления в надеюсь, что макросы появятся ;-) ... тем временем, я думаю, что я закреплю имена классов в каждом локальном варианте модуля Measure (т.е. использую менеджер пакетов, чтобы общий код предоставлялся "родительским" модулем, а затем каждым дочерняя версия — это локализованная версия... ценим рекомендации!
Я не думаю, что макросы также решат вашу проблему, поскольку они также запускаются во время компиляции. Не могли бы вы привести пример того, что вы планируете сделать? Чтобы мы могли увидеть, понимаем ли мы друг друга?
извините, макросы были в стороне --- я не продумал это настолько, чтобы задать убедительный вопрос
Спасибо за ваш быстрый ответ --- это еще половина дела, пока все хорошо, но я хочу иметь возможность выбирать разные имена классов, например
<Longueur Masse Temps>
, из файла локализации... так могу ли я объявлять имена классов также динамически?