首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >私有属性的绑定: nqp::bindattr与:=

私有属性的绑定: nqp::bindattr与:=
EN

Stack Overflow用户
提问于 2018-10-02 17:03:34
回答 1查看 113关注 0票数 10

我试图找出绑定操作是如何在属性上工作的,以及是什么使它与nqp::bindattr有如此大的不同。请考虑以下示例:

代码语言:javascript
复制
 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;

它打印:

$["a", "b", "c"]

用注释中的绑定运算符替换nqp::bindattr可以得到正确的输出:

["a", "b", "c"]

类似地,如果foo是一个公共属性,并且使用了访问器,那么由于访问器内部发生反特化,输出也将是正确的。

我在AttrX::Mooish模块中使用类似的代码,其中使用:=会使实现过于复杂。到目前为止,nqp::bindattr为我做了很好的工作,直到上面的问题出现为止。

我试图跟踪Rakudo的内部元素,寻找:=实现,但到目前为止没有取得任何成功。我想在这里要求一个关于如何模拟操作符的建议,或者在源中寻找它的实现的位置。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-02 18:14:27

在我深入研究答案之前:这篇文章中的大部分内容都是由实现定义的,而且将来实现可以自由地以不同的方式定义它们。

要找出在Rakudo 6下编译的东西(天真地),请使用--target=ast选项(perl6 --target=ast foo.p6)。例如,绑定:

代码语言:javascript
复制
class C {
    has $!a;
    submethod BUILD() {
        my $x = [1,2,3];
        $!a := $x
    }
}

以下列形式出现:

代码语言:javascript
复制
                              - QAST::Op(bind)  :statement_id<7>
                                - QAST::Var(attribute $!a) <wanted> $!a
                                  - QAST::Var(lexical self) 
                                  - QAST::WVal(C) 
                                - QAST::Var(lexical $x)  $x

在将其转换为@!a时,如下所示:

代码语言:javascript
复制
class C {
    has @!a;
    submethod BUILD() {
        my $x = [1,2,3];
        @!a := $x
    }
}

以下列形式出现:

代码语言:javascript
复制
                              - 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) 

decont指令是这里最大的区别,它将通过调用它的FETCH来获取Proxy的内容,因此容器化就消失了。因此,您可以通过在nqp::decont周围插入Proxy来复制行为,尽管这就回避了一个问题:如果没有正确的答案,Proxy在那里做什么!

:==都是使用案例分析(即通过查看左手边的内容)进行编译的。:=只适用于左侧的有限范围的简单表达式;它显然是一个低级操作符。相反,如果案例分析没有提供更有效的发出形式,那么=就回到了sub调用,尽管在大多数情况下它管理的更好。

:=的案例分析在目标是带有sigil @%的词法或属性时插入decont,因为--在Perl 6级别--将项绑定到@%没有意义。使用nqp::bindattr会降低Perl 6的语义,因此可以直接使用Proxy绑定。然而,这也违背了其他方面的期望。不要指望这样做会很顺利(但看来你无论如何都不想这么做)。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52613076

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档