我试图找到绑定操作如何对属性起作用以及它与之如何不同nqp::bindattr.请考虑以下示例:
class Foo {
has @!foo;
submethod TWEAK {
my $fval = [<a b c>];
use nqp;
nqp::bindattr( nqp::decont(self), $?CLASS, '@!foo',
#@!foo :=
Proxy.new(
FETCH => -> $ { $fval },
STORE => -> $, $v { $fval = $v }
)
);
}
method check {
say @!foo.perl;
}
}
my $inst = Foo.new;
$inst.check;
Run Code Online (Sandbox Code Playgroud)
它打印:
$["a", "b", "c"]
nqp::bindattr从注释中替换绑定运算符可以得到正确的输出:
["a", "b", "c"]
类似地,如果foo使用公共属性和访问器,则由于在访问器内发生去聚合,输出也是正确的.
我在我的AttrX::Mooish模块中使用类似的代码,其中使用:=会使实现过度复杂化.到目前为止,nqp::bindattr在上述问题出现之前,我做得很好.
我试图追查Rakudo的内部寻找:=实施但到目前为止没有任何成功.我会在这里询问有关如何模拟运算符或在源中查找其实现的建议.
Jon*_*ton 10
在我深入研究答案之前:本文中的大多数内容都是实现定义的,并且实现可以在将来以不同方式对它们进行不同的定义.
要找出在Rakudo Perl 6下编译的内容(天真),请使用--target=ast选项(perl6 --target=ast foo.p6).例如,绑定在:
class C {
has $!a;
submethod BUILD() {
my $x = [1,2,3];
$!a := $x
}
}
Run Code Online (Sandbox Code Playgroud)
出来是:
- QAST::Op(bind) :statement_id<7>
- QAST::Var(attribute $!a) <wanted> $!a
- QAST::Var(lexical self)
- QAST::WVal(C)
- QAST::Var(lexical $x) $x
Run Code Online (Sandbox Code Playgroud)
在@!a这里切换它时:
class C {
has @!a;
submethod BUILD() {
my $x = [1,2,3];
@!a := $x
}
}
Run Code Online (Sandbox Code Playgroud)
出来是:
- QAST::Op(bind) :statement_id<7>
- QAST::Var(attribute @!a) <wanted> @!a
- QAST::Var(lexical self)
- QAST::WVal(C)
- QAST::Op(p6bindassert)
- QAST::Op(decont)
- QAST::Var(lexical $x) $x
- QAST::WVal(Positional)
Run Code Online (Sandbox Code Playgroud)
这里的decont指令是最大的区别,它将Proxy通过调用它来获取内容FETCH,因此容器化的原因就消失了.因此,你可以通过nqp::decont在周围插入来复制行为Proxy,尽管Proxy如果没有它就能得到正确的答案,那么就要回答那里正在做什么的问题!
双方:=并=采用案例分析汇编(即,通过看什么是左侧).:=仅适用于左侧有限范围的简单表达; 它是一个明确的低级别运营商.相比之下,如果案例分析没有提供更有效的发布方式,则会=回退到sub呼叫,尽管在大多数情况下它会更好地管理.
:=插入的情况分析a decont当目标是词汇或具有sigil的属性时,@或者%- 在Perl 6级别 - 具有绑定到@或%没有意义的项目.使用nqp::bindattr是低于Perl 6语义的级别,因此可以Proxy使用它直接结束绑定.但是,它也违反了其他地方的期望.不要指望顺利(但似乎你不想这样做.)
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |