Para una biblioteca que estoy escribiendo, tengo un atributo en un CÓMO que usa el handles
rasgo para delegar métodos de varios roles realizados por otro CÓMO que usa a una instancia de ese CÓMO. Mi primer intento se veía así (aunque para hacer esto más fácil de leer, esto solo se resolverá Metamodel::Naming
):
class ParentHOW does Metamodel::Naming {
method new_type(ParentHOW:_: Str:D :$name!, Str:D :$repr = 'P6opaque' --> Mu) {
my ::?CLASS:D $meta := self.new;
my Mu $type := Metamodel::Primitives.create_type: $meta, $repr;
$meta.set_name: $type, $name;
$type
}
}
class ChildHOW {
has Mu $!parent;
has Mu $!parent_meta handles <set_name shortname set_shortname>;
submethod BUILD(ChildHOW:D: Mu :$parent is raw) {
$!parent := $parent;
$!parent_meta := $parent.HOW;
}
method new_type(ChildHOW:_: Mu :$parent is raw) {
my ::?CLASS:D $meta := self.new: :$parent;
Metamodel::Primitives.create_type: $meta, $parent.REPR
}
method name(ChildHOW:D: Mu \C --> Str:_) { ... }
}
my Mu constant Parent = ParentHOW.new_type: :name<Parent>;
my Mu constant Child = ChildHOW.new_type: :parent(Parent);
say Child.^shortname; # OUTPUT: Parent
El problema con esto es que si alguno de los tipos que hago de este CÓMO maneja métodos para cambios, esto ya no funcionará con todos sus métodos. Entonces, en cambio, quiero generar dinámicamente una lista de métodos que deben manejarse dada una lista de métodos que este CÓMO anula y una lista de tipos cuyos métodos deberían manejarse. Esto no es tan fácil como parece debido a cómo handles
se implementa el rasgo. Por ejemplo, esto no funcionará:
has Mu $!parent_meta handles do {
my Array[Str:D] constant PARENT_METHOD_OVERRIDES .= new: <name>;
((), Metamodel::Naming)
.reduce({ (|$^methods, |$^role.HOW.methods: $^role) })
.map(*.name)
.grep(PARENT_METHOD_OVERRIDES ∌ *)
};
Entonces, ¿cómo generaría dinámicamente un valor para que un rasgo lo use en casos como este?