是否可以在运行时内省标量的范围?
Is it possible to introspect into the scope of a Scalar at runtime?
如果我有以下变量
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
变量。像任何词汇一样,它存在于 lepad 中。唯一不同的是,它会在第一次进入范围时有效地生成代码来进行初始化。
正如 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});
}
};
这段代码在 QAST 的 Rakudo 实现细节上显然很漂亮 fragile/dependent。希望使用 RAST 这会容易得多,但这种基本方法已经可行,与此同时,guide to QAST hacking 是此类元编程的有用资源。
如果我有以下变量
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
变量。像任何词汇一样,它存在于 lepad 中。唯一不同的是,它会在第一次进入范围时有效地生成代码来进行初始化。
正如 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});
}
};
这段代码在 QAST 的 Rakudo 实现细节上显然很漂亮 fragile/dependent。希望使用 RAST 这会容易得多,但这种基本方法已经可行,与此同时,guide to QAST hacking 是此类元编程的有用资源。