我已经定义了自己的元模型类来创建一种特殊的类.现在,我希望这些类能够自动注册一个特殊的经理.基本上,这就像这样(只有在每次加载类模块时才会调用):
use MyManager; class MyHOW is Metamodel::ClassHOW { method compose ( Mu \type ) { self.add_parent( type,MyParentClass ); callsame; registerMyClass( type ); } }
然后我有类似的东西:
use v6; use MyClass; myclass Foo { ... }
在一个模块中.然后有一个管理器对象,它扫描存储库/文件系统,并要求名称与某个模式匹配的模块.之后,它需要知道每个模块中定义的myclasses.它可以扫描加载模块的符号表.但是如果加载的文件包含多个模块或根本没有模块,这将无法工作 – 如上例所示.
解决方法
在进行元编程时,在编译期间调用元对象的方法,因为解析了声明.因此,在解析myclass foo {}声明之后立即调用compose方法.然后保存模块编译的结果,并在加载模块时再次处理元对象中的任何内容.
我没有任何支持的方法可以将一个加载时回调注入到声明类型的模块中.但是,可以将符号安装到单独的包中 – 用作注册表 – 然后在那里找到它们.
例如,假设我有一个lib / MyClass.pm6,如下所示:
package MyRegistry { } class MyParentClass { } class MyHOW is Metamodel::ClassHOW { method compose ( Mu \type ) { MyRegistry::{self.name(type)} = type; self.add_parent( type,MyParentClass ); callsame; } } my package EXPORTHOW { package DECLARE { constant myclass = MyHOW; } }
我写了一些文件mods / A.pm6和mods / B.pm6像这样:
use MyClass; myclass A { }
还有这个:
use MyClass; myclass B { }
然后,当我在这样的脚本中要求它们并将密钥转储到MyRegistry中时,它们都将在那里注册:
use MyClass; for dir('mods',test => /pm6$/) { require $_; } dd MyRegistry.WHO.values;
从而提供了一种可预测的方法来找到它们.
请注意,对于这样的技术来说,你真的需要将它们存储到Stash中,因为加载器知道如何对它们进行符号合并,而在编译不同模块期间以不同方式触摸的其他类型将导致加载 – 时间冲突.
您将面临轻微的挑战,确保在一个足够独特的密钥下安装所有东西;我在这里使用的类型名称通常可能不够独特.可能我只是产生足够随机的东西,以至于碰撞的可能性极小.