【发布时间】:2018-07-31 17:23:59
【问题描述】:
我即将为新项目选择使用哪种语言:Perl5 或 Perl6。到目前为止 6 胜,只是它缺少 Moo 的惰性属性。我在模块中找到的两个实现缺少关键功能。因此,我尝试编写自己的实现。
角色与类
我遇到的第一个问题是在角色中声明的属性.package 的内容。考虑以下几点:
role HOW1 {
method compose ( Mu $class ) {
note "HOW1.compose";
nextsame;
}
}
role HOW2 {
method compose ( Mu $class ) {
note "HOW2.compose";
nextsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$mooish!) {
note "Attribute's package.HOW: ", $attr.package.HOW;
note '$*PACKAGE.HOW: ', $*PACKAGE.HOW;
$attr.package.HOW does HOW1;
$*PACKAGE.HOW does HOW2;
}
class Foo {
has $.bar is mooish;
}
role FooRole {
has $.baz is mooish;
}
脚本的输出如下:
Attribute's package.HOW: Perl6::Metamodel::ClassHOW.new
$*PACKAGE.HOW: Perl6::Metamodel::ClassHOW.new
HOW2.compose
HOW1.compose
Attribute's package.HOW: Perl6::Metamodel::GenericHOW.new
$*PACKAGE.HOW: Perl6::Metamodel::ParametricRoleHOW.new
HOW2.compose
从输出中可以清楚地看出,将角色应用于元类始终适用于类,并且仅适用于带有角色的$*PACKAGE.HOW。使用$*PACKAGE 而不是.package 可以被认为是一种解决方案,但不是我真正想要使用的解决方案。 (不过,如果没有更好的办法……)
存取器
我也想为私有属性提供惰性功能。是的,这仅适用于self!bar 语法,但这是我愿意做出的牺牲。 ???问题是到目前为止我发现的所有定制访问器示例都使用Attribute.set_value() 方法,这太低级了。我想要这样的东西:
role MooishHOW {
method compose ( Mu $class ) {
my $accessor = $class.^add_private_method( 'bar1',
method () is rw {
note self.WHO, ".bar1";
Proxy.new(
FETCH => -> $o {
$!bar1;
},
STORE => method ( $val ) {
note "Storing";
$!bar1 = $val;
}
);
}
);
callsame;
}
}
multi trait_mod:<is> (Attribute:D $attr, :$mooish!) {
$attr.package.HOW does MooishHOW unless $attr.package.HOW ~~ MooishHOW;
}
class Foo {
has $.bar is mooish;
has $!bar1 is mooish;
method to-bar1 {
note "bar1 val:",self!bar1;
}
}
my $inst = Foo.new;
$inst.to-bar1;
但$!bar1 表示法由于作用域 (MooishRole) 而无法编译。是否有我遗漏的技巧可以允许在 self 上引用私有属性?
棘手的一个
也许可以将属性设为Proxy 容器?这将大大简化惰性实现的整体逻辑。
【问题讨论】:
-
FWIW,我一直在考虑将Object::Trampoline 的功能融入属性特征。第一次尝试并没有立即成功:-(
-
Re: 使用
Proxy:class A { has $!a; method a() is raw { Proxy.new } }应该可以解决问题吗? -
你的技巧仍然需要一个访问器方法。我希望的是能够拦截
$!b。如果$!b是Proxy应该是可能的,但问题是如何做到这一点。虽然这是我的小愿望,完全可以忽略不计。我现在想要解决的是允许Nil参数用于以下内容:sub genp (::T $) { Proxy.new( STORE => method (T $v) {...} ) }。它目前在存储Nil时死机,因为当sub genp(Int) = Nil时类型不匹配(当然,Nil ~~ Int是假的)。 -
我目前正忙于调整集合运算符,如 stackoverflow.com/questions/51580534/… 中所讨论的那样,之后会看看这个(可能今天晚些时候)