代码之家  ›  专栏  ›  技术社区  ›  codesections

是否有可能在运行时反思标量的范围?

  •  0
  • codesections  · 技术社区  · 4 年前

    如果我有以下变量

    my $a    = 0;
    my $*b   = 1;
    state $c = 2;
    our $d   = 3;
    

    我可以很容易地确定 $*b 是动态的,但 $a 不包含以下代码

    say $a.VAR.dynamic;
    say $*b.VAR.dynamic;
    

    是否有类似的方法来确定 $c 是一个状态变量,并且 $d 是包作用域变量吗?(我知道我可以用一个 will 虽然每个变量声明都有trait,但我认为有一种方法不需要对每个声明都进行注释。也许有什么:(…)插值?)

    0 回复  |  直到 4 年前
        1
  •  6
  •   Elizabeth Mattijsen    4 年前

    对于包作用域变量,不要太难:

    our $foo = 'bar';
    say $foo.VAR.name ∈ OUR::.keys
    

    我们在哪里使用 OUR pseudopackage 然而,没有所谓的 STATE 伪包。他们显然出现在 LEXICAL 伪包,但我找不到一种方法来检查它们是否是状态变量。对不起的。

        2
  •  5
  •   Elizabeth Mattijsen    4 年前

    据我所知,没有办法识别 state 变量。像任何词汇一样,它存在于词汇板中。唯一不同的是,它有效地生成了代码,以便在第一次进入作用域时进行初始化。

        3
  •  3
  •   codesections    4 年前

    正如Elizabeth Mattijsen正确指出的那样,目前无法判断变量是否是 state 变量在运行时。。。至少 技术上 在运行时。

    然而,正如乔纳森·沃辛顿的评论所暗示的那样 可以在编译时检查这一点。而且,在没有深度元编程恶作剧的情况下,变量是否是 状态 变量在编译后是不可变的。当然,也可以在编译时记录一些信息,然后在运行时使用。

    因此,在运行时可以知道变量是否是 状态 一个包含以下行的(编译时)代码,它提供了 list-state-vars 列出所有特征 状态 函数中的变量:

    multi trait_mod:<is>(Sub \f, :$list-state-vars) {
        use nqp;
        given f.^attributes.first({.name eq '@!compstuff'}).get_value(f)[0] {
           say .list[0].list.grep({try .decl ~~ 'statevar'}).map({.name});
        }
    };
    

    这段代码显然非常脆弱/依赖于QAST的Rakudo实现细节。希望使用RAST会更容易,但这种基本方法已经可行,与此同时 guide to QAST hacking 是这种元编程的有用资源。