使用特征将代理应用于变量(不是属性)
这个问题与Apply a proxy using traits几乎重复。但是,这个问题涉及将代理应用于属性,我想对变量做同样的事情。从乔纳森的回答中,我明白我
需要安排将 Proxy 绑定到属性中,以便那里有一个 Proxy 而不是通常由类初始化逻辑创建的 Scalar 容器。
但是,即使在编译时,我似乎也无法成功绑定到 Variable:D。(包括 nqp::bind)。我将不胜感激任何指向正确方向的指针。
(理想情况下,我想支持使用带有赋值语法的变量/特征。在一个完美的世界中,我的语法如下:
my $thing is custom-proxy = 42;
my $thing is custom-proxy = 42;
其结果将是$thing在代理内部容器化,而不是在标量中。但是,如果这不可能,我会满足于通过绑定来使用它:=。
[编辑:建立在下面接受的答案的基础上,主要可以使用以下代码来做到这一点:
multi trait_mod:<is>(Variable v, :$tom) {
v.block.add_phaser(
'ENTER',
v.willdo(<-> $_ {
$_ = Proxy.new:
STORE => -> $, $v { say "store $v" },
FETCH => { say "fetch!"; 42}
}, 1))
}
这适用于未初始化为不同值的state变量或调用函数而不是第一个的变量。
回答
你可以随时绑定。
my $actual-thing = 42;
my $thing := Proxy.new(
FETCH => anon method fetch () {
say 'fetch';
$actual-thing
},
STORE => anon method store ($new) {
say 'store ',$new;
$actual-thing = $new
}
);
say $thing;
$thing = 5;
say $thing;
目前导致以下结果。
fetch
fetch
fetch
fetch
fetch
fetch
fetch
42
store 5
fetch
fetch
fetch
fetch
fetch
fetch
fetch
5
(重复FETCH调用是一个已知的限制。)
如果你想要像这样的语法
你需要从
multi trait_mod:<is> ( Variable:D var, :$custom-proxy! ){
…
}
问题是目前这样做需要很多我不具备的深厚的 Rakudo/nqp 知识。
例如后面的代码my $var is default('value')看起来有点像这样:
multi sub trait_mod:<is>(Variable:D $v, Mu :$default!) {
my $var := $v.var;
my $what := $var.VAR.WHAT;
my $descriptor;
{
$descriptor := nqp::getattr($var, $what.^mixin_base, '$!descriptor');
CATCH {
my $native = $v.native($what);
…
}
}
…
$descriptor.set_default(nqp::decont($default));
# make sure we start with the default if a scalar
$var = $default if nqp::istype($what, Scalar);
}
为什么有$what.^mixin_base?
我不知道。
为什么不能$!descriptor访问类似的东西$v.var.descriptor?
我不知道。
我们如何$v.var.VAR从 aScalar变为 a Proxy?
我不知道。
最后一个可行吗?(从 a 中trait_mod:<is>)我相当肯定答案是肯定的。