Как мне узнать все роли, которые выполняет Perl 6? - PullRequest
0 голосов
/ 18 мая 2018

С помощью .does я могу проверить, имеет ли тип ту роль, которую я уже знаю.Я хотел бы получить список ролей.Наследование имеет .^mro, но я не видел ничего подобного для ролей в метамодели.

Наряду с этим, учитывая «тип», как я могу определить, определено ли оно как класс илироль?

Ответы [ 4 ]

0 голосов
/ 18 мая 2018

Уже есть хороший ответ на первый вопрос. Что касается второго, у каждого метаобъекта есть метод archetypes, который, в свою очередь, несет диапазон свойств типов, представленных этим мета-типом. Это существует потому, что Perl 6 открыт для новых мета-типов (о которых проще думать как о «типах типов»); вероятно, наиболее широко используемый пример этого сегодня - OO::Monitors. Архетипы больше сосредоточены на том, что можно сделать с типом. Например:

> role R { }; say "C: {.composable} I: {.inheritable}" given R.HOW.archetypes; 
C: 1 I: 0
> class C { }; say "C: {.composable} I: {.inheritable}" given C.HOW.archetypes; 
C: 0 I: 1

Набор доступных свойств может быть проанализирован:

> Int.HOW.archetypes.^methods(:local)
(nominal nominalizable inheritable inheritalizable composable 
composalizable generic parametric coercive definite augmentable)

Например, «номинальный» означает «может ли это служить номинальным типом», а «расширяемый» означает «разрешено ли увеличивать этот тип». Такие вещи, как «унаследованные», означают «могу ли я наследовать такой тип», то есть превратить его в тип, от которого я могу унаследовать, даже если я не могу наследовать от этого типа. role не наследуется, но наследуемо, и операция наследования над ним произведет каламбур роли. Это то, что происходит внутри, когда пишется что-то вроде class C is SomeRole { }, и это означает, что Perl 6 не только открыт для новых типов типов, но и эти новые типы типов могут описывать, как они хотят работать, если вообще работают с наследование и состав.

Возможность компоновки с does, вероятно, является основным определяющим свойством роли, и, таким образом, свойство composable, вероятно, является лучшим для использования при запросе "Является ли это ролью". Также можно посмотреть на тип мета-объекта, как предложено в другом ответе, но есть несколько мета-объектов, участвующих в представлении ролей (группа ролей с коротким именем, карринг этой группы с параметрами и отдельный индивид). роль, плюс внутренняя форма конкретизации, которая поддерживает процесс композиции).

> say (role RRR[::T] { }).HOW.^name
Perl6::Metamodel::ParametricRoleHOW
> say RRR.HOW.^name
Perl6::Metamodel::ParametricRoleGroupHOW
> say RRR[Int].HOW.^name
Perl6::Metamodel::CurriedRoleHOW

Таким образом, гораздо надежнее просто проверить, является ли эта вещь составной.

> say (role RRR[::T] { }).HOW.archetypes.composable
1
> say RRR.HOW.archetypes.composable
1
> say RRR[Int].HOW.archetypes.composable
1
0 голосов
/ 18 мая 2018

Относительно вашего второго вопроса,

учитывая "тип", как я могу определить, определен ли он как класс или роль?

Я не нашел прямого способа сделать это. И классы, и роли имеют Mu в своей иерархии, поэтому они не будут различаться. Однако, только классы могут быть признаны (с любопытством названными) MetaModel::ClassHOW. Таким образом, мы можем взломать что-то вроде этого:

role Ur { }
role F does Ur { }
class G does F { }
for Ur, F, G -> $class-or-role {
    CATCH {
        default {
            say "not classy";
        }
    }
    $class-or-role.say;
    $class-or-role.^mro.say;
}

Который напечатает:

(Ur)
not classy
(F)
not classy
(G)
((G) (Any) (Mu))

, поскольку вызов ^mro для роли вызовет исключение. Это можно превратить в функцию для распечатки, какая из них является ролью, а какая нет.

0 голосов
/ 18 мая 2018

Наряду с этим, учитывая «тип», как я могу определить, определен ли он как класс или роль?

Класс - это тип, мета-класс которого имеет тип Metamodel::ClassHOW:

sub type-classify(Mu \t) {
    given t.HOW {
        return 'class' when Metamodel::ClassHOW;
        return 'role'  when Metamodel::ParametricRoleGroupHOW;
    }
    return 'other';
}
say type-classify(Int);         # class
say type-classify(Rational);    # role
say type-classify(Bool);        # other
0 голосов
/ 18 мая 2018
.^roles
say Rat.^roles; # ((Rational[Int,Int]) (Real) (Numeric))

По умолчанию оно включает все роли, включая роли, внесенные другими ролями. Чтобы получить только первый уровень используйте :!transitive

Rat.^roles(:!transitive); # ((Rational[Int,Int]))
...