Für eine Bibliothek, die ich schreibe, habe ich ein Attribut für ein WIE, das das handles
Merkmal verwendet, um Methoden verschiedener Rollen, die von einem anderen WIE ausgeführt werden, an eine Instanz dieses WIE zu delegieren. Mein erster Versuch sah so aus (obwohl dies nur einfacher zu lesen ist, wird dies nur behandelt 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
Das Problem dabei ist, dass wenn einer der Typen, die ich in diesem HOW-Verfahren verwende, Methoden für immer ändert, dies nicht mehr mit allen Methoden funktioniert. Stattdessen möchte ich dynamisch eine Liste von Methoden generieren, die mit einer Liste von Methoden behandelt werden sollen, die in diesem HOW überschrieben werden, und eine Liste von Typen, deren Methoden behandelt werden sollen. Dies ist nicht so einfach, wie es sich anhört, da das handles
Merkmal implementiert ist. Zum Beispiel wird dies nicht funktionieren:
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 ∌ *)
};
Wie würden Sie also dynamisch einen Wert für ein Merkmal generieren, der in solchen Fällen verwendet werden kann?