使用特征将代理应用于变量(不是属性)
Apply a proxy to a variable (not an attribute) using traits
这个问题几乎与 重复。但是,该问题涉及将代理应用于属性,我想对变量做同样的事情。从乔纳森的回答中,我了解到我
need to arrange for the Proxy to be bound into the attribute, so that there's a Proxy there rather than a Scalar container that is usually created by class initialization logic.
但是,即使在编译时,我似乎也无法成功绑定到 Variable:D。 (包括 nqp::bind)。我将不胜感激任何指向正确方向的指示。
(理想情况下,我想支持使用 variable/trait 和赋值语法。在完美的世界中,我的语法如下:
my $thing is custom-proxy = 42;
其结果是 $thing
被容器化在 Proxy 中,但 而不是 在 Scalar 中。但如果那不可能,我会满足于通过 :=
.
让它与绑定一起工作
[编辑:基于下面接受的答案,可以主要使用以下代码执行此操作:
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
调用是已知限制。)
如果你想要
这样的语法
my $thing is custom-proxy = 42;
您需要从
开始
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
从 Scalar
更改为 Proxy
?
我不知道。
最后一个可行吗? (来自trait_mod:<is>
内)
我很确定答案是肯定的。
我的2d[1]:
I'd settle for getting it working with binding via :=
.
sub custom-proxy is rw { Proxy.new: FETCH => { 42 }, STORE => { ... } }
my $variable := custom-proxy;
say $variable; # 42
In a perfect world, I'd have syntax like:
my $thing is custom-proxy = 42;
哎呀,这是@Larry 的意图。
但是,正如您可能知道的那样,如果使用 is
特征将类型(例如 role custom-proxy { ... }
)应用于 标量 变量(例如 my $variable is custom-proxy
) 然后编译器发出编译时错误消息 (is trait on $-sigil variable not yet implemented
).
I can't seem to bind successfully to a Variable:D
, even at compile time
首先,让我们澄清一下 Variable
是什么,以及您需要成功绑定到什么:
multi trait_mod:<is>(Variable \var, :$foo!) { say var.var.VAR.WHAT } # (Scalar)
my $variable is foo;
您可能认为可以绑定到 var
。但是编译器传递的是左值,因此您无法更改它。
您可能认为可以绑定到 var.var
,这是 Variable
的一个属性。 (我解释了 Variable
是什么,它的 var
属性,以及为什么我必须在上面的代码中写“varvarVAR!”,。)
您链接的 SO 显示了如何更改绑定到某些对象中属性的值:
$a.set_build: -> \SELF, | {
$a.set_value: SELF, Proxy.new:
STORE => -> $, $val { say "store $val" },
FETCH => { say "fetch!"; 42 }
}
所以也许您可以使用该方法来更改 Variable
的 .var
属性?
不幸的是,“设置构建逻辑”用于“绑定属性……在每个对象创建时”,(因此“您将覆盖任何初始默认值").
所以我认为这种技术在这种情况下不会有帮助,因为 Variable
及其 .var
属性大概在 Variable
传递给 is
特征。
总而言之,虽然 是 在编译时调用的特性,但我认为它被调用 太迟了 因为 var
属性已经永久绑定
我的猜测是改变 Raku(do) 以便 Variable
的 .var
属性变得可写,或者使用元编程潜入 Variable
的 public API 强制通过更改,这将是令人担忧的,不合理地使编译器的变量处理代码复杂化 and/or 将代码生成优化逻辑换成悲观化逻辑。
这可能是@Larry 推测有朝一日会实施对标量变量更受控制的 is type
的原因。
脚注
[1]我的两个(便士|狗狗币)。
这个问题几乎与
need to arrange for the Proxy to be bound into the attribute, so that there's a Proxy there rather than a Scalar container that is usually created by class initialization logic.
但是,即使在编译时,我似乎也无法成功绑定到 Variable:D。 (包括 nqp::bind)。我将不胜感激任何指向正确方向的指示。
(理想情况下,我想支持使用 variable/trait 和赋值语法。在完美的世界中,我的语法如下:
my $thing is custom-proxy = 42;
其结果是 $thing
被容器化在 Proxy 中,但 而不是 在 Scalar 中。但如果那不可能,我会满足于通过 :=
.
[编辑:基于下面接受的答案,可以主要使用以下代码执行此操作:
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
调用是已知限制。)
如果你想要
这样的语法my $thing is custom-proxy = 42;
您需要从
开始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
从 Scalar
更改为 Proxy
?
我不知道。
最后一个可行吗? (来自trait_mod:<is>
内)
我很确定答案是肯定的。
我的2d[1]:
I'd settle for getting it working with binding via
:=
.
sub custom-proxy is rw { Proxy.new: FETCH => { 42 }, STORE => { ... } }
my $variable := custom-proxy;
say $variable; # 42
In a perfect world, I'd have syntax like:
my $thing is custom-proxy = 42;
哎呀,这是@Larry 的意图。
但是,正如您可能知道的那样,如果使用 is
特征将类型(例如 role custom-proxy { ... }
)应用于 标量 变量(例如 my $variable is custom-proxy
) 然后编译器发出编译时错误消息 (is trait on $-sigil variable not yet implemented
).
I can't seem to bind successfully to a
Variable:D
, even at compile time
首先,让我们澄清一下 Variable
是什么,以及您需要成功绑定到什么:
multi trait_mod:<is>(Variable \var, :$foo!) { say var.var.VAR.WHAT } # (Scalar)
my $variable is foo;
您可能认为可以绑定到 var
。但是编译器传递的是左值,因此您无法更改它。
您可能认为可以绑定到 var.var
,这是 Variable
的一个属性。 (我解释了 Variable
是什么,它的 var
属性,以及为什么我必须在上面的代码中写“varvarVAR!”,
您链接的 SO 显示了如何更改绑定到某些对象中属性的值:
$a.set_build: -> \SELF, | {
$a.set_value: SELF, Proxy.new:
STORE => -> $, $val { say "store $val" },
FETCH => { say "fetch!"; 42 }
}
所以也许您可以使用该方法来更改 Variable
的 .var
属性?
不幸的是,“设置构建逻辑”用于“绑定属性……在每个对象创建时”,(因此“您将覆盖任何初始默认值").
所以我认为这种技术在这种情况下不会有帮助,因为 Variable
及其 .var
属性大概在 Variable
传递给 is
特征。
总而言之,虽然 是 在编译时调用的特性,但我认为它被调用 太迟了 因为 var
属性已经永久绑定
我的猜测是改变 Raku(do) 以便 Variable
的 .var
属性变得可写,或者使用元编程潜入 Variable
的 public API 强制通过更改,这将是令人担忧的,不合理地使编译器的变量处理代码复杂化 and/or 将代码生成优化逻辑换成悲观化逻辑。
这可能是@Larry 推测有朝一日会实施对标量变量更受控制的 is type
的原因。
脚注
[1]我的两个(便士|狗狗币)。