Альтернативный синтаксис для интроспективных модулей / классов / и т. Д.

Я переписываю фреймворк с 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 или ссылка на разыскиваемый саб.

Другие вопросы по тегам