If I have the following variables
my $a = 0;
my $*b = 1;
state $c = 2;
our $d = 3;
I can easily determine that $*b
is dynamic but $a
is not with the following code
say $a.VAR.dynamic;
say $*b.VAR.dynamic;
Is there any way to similarly determine that $c
is a state variable and $d
is a package-scoped variable? (I know that I could do so with a will
trait on each variable declaration, but I'm hopping there is a way that doesn't require annotating every declaration. Maybe something with ::(...) interpolation?)
The introspection endpoint does not necessarily need to return the same information for all queries of the same token. For example, two different resource servers (if they authenticate themselves when making the introspection request) may get different views of the state of the token.
A lot is possible in mathematics, and I will sketch, right now, a simple method of encoding a vector as a scalar; but I warn - this method has no uses. I am unaware of any useful methods of encoding a vector with real components as a scalar.
A vector has a scalar magnitude and a direction that can be expressed as a unit vector. You can take the magnitude of any vector: A = | A → | and you can turn any scalar into a vector by multiplying it by a unit vector: A → = A a ^ where a ^ = A → A. How is a scalar converted into a vector?
Consumers of the introspection endpoint may wish to cache the response of the endpoint for performance reasons. As such, it is important to consider the performance and security trade-offs when deciding to cache the values.
In the case of the package-scoped variable, not too hard:
our $foo = 'bar';
say $foo.VAR.name ∈ OUR::.keys
where we're using the OUR
pseudopackage. However, there's no such thing as a STATE
pseudopackage. They obviously show up in the LEXICAL
pseudopackage, but I can't find a way to check if they're a state variable or not. Sorry.
To my knowledge, there is no way to recognize a state
variable. Like any lexical, it lives in the lexpad. The only thing different about it, is that it effectively has code generated to do the initialization the first time the scope is entered.
As Elizabeth Mattijsen correctly noted, it is currently not possible to see whether a variable is a state
variable at run time. ... at least technically at runtime.
However, as Jonathan Worthington's comment implies, it is possible to check this at compile time. And, absent deep meta-programming shenanigans, whether a variable is a state
variable is immutable after compile-time. And, of course, it's possible to make note of some info at compile time and then use it at runtime.
Thus, it's possible to know, at runtime, whether a variable is a state
one with (compile-time) code along the following lines, which provides a list-state-vars
trait that lists all the state
variables in a function:
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});
}
};
This code is obviously pretty fragile/dependent on the Rakudo implementation details of QAST. Hopefully this will be much easier with RAST, but this basic approach is already workable and, in the meantime, this guide to QAST hacking is a helpful resource for this sort of meta programming.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With