rakudynamic-scope

How do I test a dynamic variable for existence?


As I understand, Dynamic Variables are looked up at runtime. I want to use them to enable parametrization similar to racket parameters.

To do so, I have to set a default that should be overridable, but not necessarily changable. My current approach is fairly simplistic:

my $*param ::= 42;
sub parameterized-function { say $*param };
parameterized-function();
do {
    my $*param ::= 15;
    parameterized-function();
}

Which works just fine - except that it introduces the name of the parameter on the outer scope. Beyond just feeling untidy, this has the side-effect that my $*param = 15; causes mayhem if used on the file level.

What I would like to do instead is check if the parameter has been defined on the call stack, along the lines of:

sub parameterized-function { if defined($*param) { say 42 } else { say $*param } };

So, is it possible to perform such a check, if so how is it done?


Solution

  • Quoting S02:

    User-defined dynamic variables should generally be initialized with ::= unless it is necessary for [the] variable to be modified. (Marking dynamic variables as readonly is very helpful in terms of sharing the same value among competing threads, since a readonly variable need not be locked.)

    If you want to access a dynamic variable that has not been defined in the current (dynamic) scope, either of the following should work:

    $*param // 'default value'
    
    # Any if not found
    DYNAMIC::<$*param>
    
    # Nil if not found
    try $*param
    
    # Mu if not found
    use nqp;
    nqp::getlexdyn('$*param')
    

    As I have not looked into what you're trying to accomplish, there might be more appropriate solutions.