Most fancy
On Discord (yes, we are that cool) MrDispatch wished for a way to collect a bunch of classes right after their declaration. I believe, with the power of the MOP, we can go a step further and register the type-object even before the definition is finished.
class MetamodelX::RegisteredHOW is Metamodel::ClassHOW {
our @registered;
method new_type(|) {
my \type = callsame;
type.HOW.remember_type(type);
type
}
method remember_type(Mu \type) {
@registered.push: type
}
method recall-types {
@registered;
}
}
sub recall-types is export(:recall-types) {
MetamodelX::RegisteredHOW.recall-types;
}
my package EXPORTHOW {
package DECLARE {
constant registered = MetamodelX::RegisteredHOW;
}
}
We introduce a new declarator registered
that hooks up a new meta-class. It would be possible to overload class
to register all classes in a compilation unit. For now, doing so would not be good conduct, because playing with EXPORTHOW
is not quite lexical yet. The list of declared type objects will reside as a class-attribute inside the meta-class. We can access it through any type object or instance via .HOW
or with the exported sub recall-types
.
use v6.*;
use Registered :recall-types;
registered Foo {
method answer { 42 }
method common { self.^name }
}
registered Bar {
method ohai { ‚Hello Universe!‘ }
method common { self.^name }
}
Foo.HOW.recall-types.say;
say Foo.new.HOW.recall-types;
say recall-types; # requires the import adverb :recall-types;
say recall-types».common;
# OUTPUT: [(Foo) (Bar)]
# [(Foo) (Bar)]
# [(Foo) (Bar)]
# [Foo Bar]
There are plenty of other ways to implement a registry of types. Using a custom meta-class is the most fancy and flexible way. We could hook into many other things here too. Rakudo is a dynamic compiler for a dynamic language. It uses introspection much more then you do. Sometimes it introspects a package called EXPORTHOW for a key called DECLARE to create a keyword that is more classy then class
.