У меня есть определение перечисления в модуле AAA
:
enum RDProcDebug <None All AstBlock BlockType Scoping Templates MarkUp>;
class Debug {
method foo(RDProcDebug @ds) {
for @ds { say .key ~ ' => ' ~ .value }
}
}
В программах Raku это работает хорошо, например
use AAA;
my RDProcDebug $rp .= new;
$r.foo(AstBlock, BlockType);
Но теперь мне нужно указать имена элементов отладки из командной строки, которая может предоставить только Str, например
$ RDOpts='AstBlock BlockType' raku myprog
# and in myprog
if %*ENV<RDOpts>:exists {
$rp.debug( %*ENV<RDOpts> ); # this does not work
}
Итак, как мне преобразовать список Str в список типа enum RDProcDebug?
Хорошо, вы хотите передать эти значения перечисления из командной строки, но получаете только строки. Я понимаю. Вот что вы можете сделать:
Сначала возьмите эти RDOpts из своей среды и разделите их на отдельные слова.
my @debug-options = %*ENV<RDOpts>.split(/\s+/);
Теперь вот самое интересное. У Раку есть трюк для поиска значений перечисления по их имени. Это выглядит немного странно, но работает вот так:
my @debug-values = @debug-options.map({ RDProcDebug::{$_} });
Это проверяет каждую строку в вашем списке на наличие соответствующего значения перечисления. Если все пойдет хорошо, вы получите список фактических значений RDProcDebug. Теперь вы можете просто передать его в свой метод отладки:
$rp.debug(@debug-values);
В совокупности у вас получится что-то вроде этого:
if %*ENV<RDOpts> {
my @debug-options = %*ENV<RDOpts>.split(/\s+/);
my @debug-values = @debug-options.map({ RDProcDebug::{$_} });
$rp.debug(@debug-values);}
Ах да, еще кое-что: если кто-то введет неправильное имя, вы получите ошибку. Возможно, вы захотите что-то с этим сделать..
.map({ RDProcDebug::{$_} })
— это секретный соус (источник?), который я искал!
На самом деле это комбинация нескольких функций Raku: Синтаксис :: предназначен для доступа к символам уровня пакета. В данном случае он просматривает перечисление RDProcDebug. {} вокруг $_ означает, что мы выполняем динамический поиск. Это все равно что сказать: «Используйте строковое значение $_ в качестве ключа для поиска в RDProcDebug». .map() просто применяет это к каждому элементу в вашем списке строк. На самом деле это не задокументировано в каком-то конкретном месте, потому что здесь используется несколько разных функций Raku вместе.