我将继续深入研究Perl6细微的实现细节。这次我在将自己的方法安装到角色中时遇到了问题。在我们开始进入密码的旅程时,请系好安全带。
这个想法是一种属性特性,它在它所组成的类型对象上安装方法。这个问题最初是在私有方法上发现的,我希望它安装在属性声明的角色中。此时,我发现在某些条件下,无法调用从闭包引用标量的生成方法!很可能是因为关闭在运行时丢失。但最令人困惑的是,这种情况只会发生在角色身上,而且只会发生在一个角色正在消费另一个角色的情况下!
因此,以下是特质来源:
unit module trait-foo;
role FooClassHOW {...}
role FooAttr {
has $.base-name = self.name.substr(2);
method compose (Mu \type) {
callsame;
if (type.HOW ~~ Metamodel::ClassHOW) && (type.HOW !~~ FooClassHOW) {
type.HOW does FooClassHOW;
}
}
method install-method ( Mu \type ) {
my $attr = self;
type.^add_private_method(
"attr-{$attr.base-name}",
method { "by attr {$attr.name}" }
);
type.^add_method(
"pubattr-{$attr.base-name}",
method { "by attr {$attr.name} - public" }
);
type.^add_private_method(
"check-{$attr.base-name}",
method { "not using closure" }
);
}
}
role FooClassHOW {
method compose ( Mu \type ) {
for type.^attributes.grep( FooAttr ) -> $attr {
$attr.install-method( type );
type.^add_private_method(
"class-{$attr.base-name}",
method { "by class: attr {$attr.name}" }
);
}
nextsame;
}
}
role FooRoleHOW {
method compose ( Mu \type ) {
for type.^attributes.grep( FooAttr ) -> $attr {
$attr.install-method( type );
type.^add_private_method(
"role-{$attr.base-name}",
method { "by role: attr {$attr.name}" }
);
}
nextsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$foo!) is export {
$attr does FooAttr;
given $*PACKAGE.HOW {
when Metamodel::ParametricRoleHOW {
$_ does FooRoleHOW unless $_ ~~ FooRoleHOW;
}
default {
$_ does FooClassHOW unless $_ ~~ FooClassHOW;
}
}
}
这里的关键点是install-method
,它安装了一个公共方法pubattr-
compose_method_injectp6
#!/usr/bin/env perl6
use lib '.';
use trait-foo;
use compose-foorole;
class Foo does FooRole {
has $.fubar is foo;
method class-test {
say self!check-fubar;
say self!class-fubar;
say self!attr-fubar;
}
}
my $inst = Foo.new;
note "> Class";
$inst.class-test;
note "> BarRole";
$inst.bar-role-test;
note "> FooRole";
$inst.foo-role-test;
撰写foorole。pm6
unit package compose;
use trait-foo;
use compose-barrole;
role FooRole does BarRole is export {
has $.foo is foo;
method foo-role-test {
note FooRole.^candidates[0].^private_method_table;
say self!check-foo;
say self!role-foo;
say self!attr-foo;
}
}
compose-barrole.pm6
unit package compose;
use trait-foo;
role BarRole is export {
has $.bar is foo;
method bar-role-test {
note BarRole.^candidates[0].^private_method_table;
say self!check-bar;
say self!role-bar;
say self!inattr-bar;
}
}
执行compose_method_inject. p6会产生以下输出:
> Class
not using closure
by class: attr $!fubar
by attr $!fubar
by attr $!fubar - public
> BarRole
{attr-bar => <anon>, check-bar => <anon>, role-bar => <anon>}
not using closure
by role: attr $!bar
Cannot invoke this object (REPR: Null; VMNull)
请注意,该类工作正常,而BarRole中的类似代码失败。如果首先执行来自FooRole的foo role测试,则会观察到相同的结果:
> Class
not using closure
by class: attr $!fubar
by attr $!fubar
by attr $!fubar - public
> FooRole
{attr-foo => <anon>, check-foo => <anon>, role-foo => <anon>}
not using closure
by role: attr $!foo
Cannot invoke this object (REPR: Null; VMNull)
还值得注意的是,从
FolRoleHow
安装的方法不会丢失其闭包并已成功执行。
现在,再看另一个把戏。我将BarRole从FooRole中删除,并将其直接应用于Foo:
class Foo does FooRole does BarRole {
输出急剧变化,情况变得更加混乱:
> Class
not using closure
by class: attr $!fubar
by attr $!fubar
by attr $!fubar - public
> FooRole
{attr-foo => <anon>, check-foo => <anon>, role-foo => <anon>}
not using closure
by role: attr $!foo
by attr $!foo
> BarRole
{attr-bar => <anon>, check-bar => <anon>, role-bar => <anon>}
not using closure
by role: attr $!bar
Cannot invoke this object (REPR: Null; VMNull)
UPD需要注意的另一件重要事情是,角色和类都故意按文件拆分,因为将它们都放在公共文件中可以使事情按预期工作。
顺便说一句,我不想深入其中,但在提取上述示例的原始代码中,我还使用
设置了方法名称。set_name
。名称是字符串,包括闭包中的$attr
标量。在compose()
中转储方法表会产生以设置名称为值的哈希值;在用户代码中转储相同的表会显示与上述类似的输出-使用
现在,我想听到有人说我很愚蠢,必须以不同的方式安装方法。或者关于属性的信息必须以其他方式保存,但不能通过依赖闭包。或者任何其他可以让我创建私有属性相关方法的想法。
这并不是确切的答案,而是一个注释和bug的解决方法。好的,刚刚注意到:这是一个bug。虽然它不存在于Linux版本的rakudo中,但我只在macOS/darwin上观察到它。当然,这并不意味着其他平台不易受到攻击。
该错误有一个解决方法。由于从类/角色作曲家安装的方法不会丢失它们的闭包,因此必须将方法的安装移动到其中。在我的例子中,因为两者都需要类似的功能,所以使用角色实现方法安装程序是一种魅力。
在OWL中,不可伸缩属性的子属性也是不可伸缩的吗?同样,非对称属性的子属性也是非对称的吗? 从逻辑上讲,它们应该是这样的,但我在OWL文档中找不到任何说明这种情况的内容。 考虑以下示例: 基于此本体,不允许出现以下情况,因为的父项是不可伸缩的: 但是是否也隐含地不反射性呢?换句话说,这是否也被禁止: 如果你认为一个属性是一组连接成对的点的箭头,那么不可反身仅仅意味着没有在同一个点开始和结束的箭头。
特征值
我正在Rust中编写一个带有控制台提示界面的进程内存扫描器。 我需要扫描仪类型,如winapi扫描仪或ring0驱动程序扫描仪,所以我试图实现多态性。 目前我有以下结构: 将来,除了 之外,我还会有更多扫描仪类型,因此,如果我理解正确,我应该使用特征引用 (
问题内容: 我正在调整我的一个宠物项目以提高其性能。我已经淘汰了探查器以识别热点,但是我认为对Python性能特性的了解要好一些,这将非常有用。 我想知道几件事: 一些现代的编译器拥有非常聪明的优化器,它们通常可以采用简单的代码,并使其运行速度比任何人工调整代码的尝试都要快。根据优化器的智能程度,使我的代码“哑巴”可能更好。 尽管Python是一种“解释”语言,但它确实可以编译为某种形式的字节码(
我用openlayers 3在地图中上传了一个geojson文件。geojson文件是一个FeatureCollection,具有LineString类型的5个功能。如何为每个功能添加不同的颜色以区分路径?如果我将颜色添加到geojson文件的样式中,则不会读取该文件,如果我将颜色添加到笔划中,则所有功能都以单一颜色着色。 下面我添加代码。 谢谢 文件GEOJSON: "type":"Featur
我正在使用云形成和yaml语法设置AWS ECS服务。 在某个时候,在相关的留档中有一个名为的属性,其定义如下: 角色 AWS标识和访问管理(IAM)角色的名称或ARN,该角色允许Amazon ECS容器代理调用负载平衡器。 注意:在某些情况下,可能需要添加对服务角色策略的依赖关系。有关详细信息,请参阅DependsOn属性中的IAM角色策略。必需:无类型:字符串更新需要:替换 由于我打算将特定服