cod*_*ons 7 introspection rakudo raku
如果我有以下变量
my $a = 0;
my $*b = 1;
state $c = 2;
our $d = 3;
Run Code Online (Sandbox Code Playgroud)
我可以很容易地确定这$*b是动态的,但$a不是下面的代码
say $a.VAR.dynamic;
say $*b.VAR.dynamic;
Run Code Online (Sandbox Code Playgroud)
有什么方法可以类似地确定它$c是状态变量$d还是包范围的变量?(我知道我可以用will每个变量声明的特征来做到这一点,但我希望有一种不需要注释每个声明的方法。也许有 ::(...) 插值?)
在包范围变量的情况下,不要太难:
our $foo = 'bar';
say $foo.VAR.name ? OUR::.keys
Run Code Online (Sandbox Code Playgroud)
我们在哪里使用OUR伪包。但是,没有STATE伪包这样的东西。它们显然出现在LEXICAL伪包中,但我找不到检查它们是否是状态变量的方法。对不起。
正如 Elizabeth Mattijsen 正确指出的那样,目前无法state在运行时查看变量是否是变量。...至少在运行时技术上是这样。
然而,正如 Jonathan Worthington 的评论所暗示的那样,可以在编译时检查这一点。而且,如果没有深层元编程恶作剧,变量是否是变量state在编译后是不可变的。当然,可以在编译时记下一些信息,然后在运行时使用它。
因此,可以在运行时知道变量是否是state具有以下几行(编译时)代码的变量,它提供了一种列出函数中list-state-vars所有变量的特征:state
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});
}
};
Run Code Online (Sandbox Code Playgroud)
这段代码显然非常脆弱/依赖于 QAST 的 Rakudo 实现细节。希望使用 RAST 会更容易,但这种基本方法已经可行,同时,本QAST 黑客指南对于此类元编程来说是有用的资源。