Альтернативный синтаксис для интроспективных модулей / классов / и т. Д.
Я переписываю фреймворк с Perl5 на Perl6 для своих рабочих целей. В каком-то месте мне нужно собирать информацию из других модулей / классов, выполняя публичные sub
они могут предоставить; или они не могут. Таким образом, необходимо выяснить, если sub
настоящее. Это не имеет большого значения, когда на модуль ссылаются напрямую (Foo::<&my-sub>
) или по символическому имени в строке (&::("Foo")::my-sub). Но для простоты я хотел бы разрешить передавать имена модулей как есть (скажем, collector
метод сбора информации):
self.collector( Foo );
куда Foo
может быть следующим:
module Foo {
use Bar;
use Baz;
our sub my-sub { Bar, 'Baz' }
}
И здесь я упускаю что-то важное из синтаксиса Perl6, потому что следующее:
method collector ( $mod ) {
my $mod-name = $mod.WHO;
my @mods;
with &::($mod-name)::my-sub {
@mods.push: &$_();
}
}
в настоящее время единственный способ, которым я могу выполнить задачу.
Я еще не попробовал захват типа. Должно работать, как и ожидалось. Итак, вопрос больше в расширении моих знаний о синтаксисе.
1 ответ
Окончательное решение от обмена с Вадимом в комментариях к их вопросу. Это возможно безумие. Они думают, что это красиво. И кто я такой, чтобы спорить? .oO(Хаха, хохо, хи-хи...)
my $pkg-arg = (Int, 'Int').pick;
my \pkg-sym = $pkg-arg && ::($pkg-arg);
my \sub-ref = &pkg-sym::($subname);
Существует два очевидно полезных способа обращения к пакету:
Его символическое имя.
Int
является символическим именем класса Int.Его строковое имя.
'Int'
является строковым именем класса Int.
Вадим, достаточно разумно, хочет решения для обоих.
В решении в этом ответе я моделирую два типа аргумента, выбирая случайным образом один из них и присваивая его $pkg-arg
:
my $pkg-arg = (Int, 'Int').pick;
Теперь нам нужно нормализоваться. Если у нас есть символическое имя, мы можем пойти. Но если это строковое имя, нам нужно превратить его в символическое имя.
Вадим показал пару способов сделать это в комментариях к своему вопросу. Это решение использует третий вариант:
my \pkg-sym = $pkg-arg && ::($pkg-arg);
Если $pkg-arg
это символическое имя, это будет False
, С False
LHS &&
короткое замыкание и возвращает его LHS. Если $pkg-arg
это имя строки, то &&
вместо этого вернет свою RHS, которая ::($pkg-arg)
который является поиск символа с помощью $pkg-arg
в качестве имени строки.
Результатом является то, что pkg-sym
в конечном итоге содержит символическое имя пакета (или Failure
если поиск не смог найти подходящее символическое имя).
Который оставляет последнюю строку. Это ищет суб с именем $subname
в упаковке pkg-sym
:
my \sub-ref = &pkg-sym::($subname);
&
необходимо для обеспечения того, чтобы RHS рассматривался как ссылка, а не как попытка вызвать процедуру. А также pkg-sym
должен быть идентификатором без знака, иначе код не будет работать.
В конце этих трех строк кода sub-ref
содержит либо Failure
или ссылка на разыскиваемый саб.