问题描述
如果我有以下变量
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
特征来做到这一点,但我希望有一种不需要注释每个声明的方法。也许有 ::(...) 插值?)
解决方法
在包范围变量的情况下,不要太难:
our $foo = 'bar';
say $foo.VAR.name ∈ OUR::.keys
我们在哪里使用 OUR
pseudopackage。但是,没有 STATE
伪包这样的东西。它们显然出现在 LEXICAL
伪包中,但我找不到检查它们是否是状态变量的方法。对不起。
据我所知,无法识别 state
变量。像任何词法一样,它存在于 lexpad 中。唯一不同的是,它有效地生成了第一次进入范围时进行初始化的代码。
正如 Elizabeth Mattijsen 正确指出的那样,目前无法在运行时查看变量是否为 state
变量。 ...至少在运行时技术上。
然而,正如 Jonathan Worthington 的评论所暗示的那样, 可以在编译时检查这一点。并且,在没有深度元编程恶作剧的情况下,变量是否是 state
变量在编译时是不可变的。当然,也可以在编译时记下一些信息,然后在运行时使用。
因此,有可能在运行时知道一个变量是否是 state
一个带有(编译时)代码的变量,它提供了一个 list-state-vars
trait,它列出了所有的 {函数中的 {1}} 个变量:
state
这段代码显然非常脆弱/依赖于 QAST 的 Rakudo 实现细节。希望使用 RAST 会更容易,但这种基本方法已经可行,同时,此 guide to QAST hacking 是此类元编程的有用资源。