Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exporting of dynamically scoped variables?

Tags:

raku

Basically, the question is more about grammars but I think that it could be more of a interesting exercise on dynamic variables.

I have a grammar role with a prototyped token (the example is simplified to demonstrate the idea):

proto token foo {*}
token foo:sym<a> {
   :my $*delimiter = q<">;
   \" ~ \" <value>
}
token foo:sym<b> {
   :my $*delimiter = q<'>;
   \' ~ \' <value>
}
token value {
    .+? <?before $($*delimeter) || $($*custom-delimiter)>
}

When the role is consumed by a grammar I want the $*custom-delimiter to be set by the grammar. Of course, I can declare it everywhere where <foo> is needed. But sometimes it is ok to have it pre-initialized with a universal default. Something like:

{ $*custom-delimiter //= $default-delimiter }

in the value token would work. But external pre-declaration would still be needed.

I hoped that:

our $*custom-delimiter is export = $default-delimiter;

in the scope of module where the role is declared would work. But apparently it doesn't. So, the question is: are there any elegant solutions to this?

Actually, I also hope that the solution would allow to move declaration of $*delimiter in foo outside of the token definitions too.

As a side note: my first thought was about adding a parameter to the token. But having absolutely identical signatures for each variant is looking terrible too:

token foo:sym<a> ( $*custom-delimiter = $default-delimiter ) {
}
token foo:sym<b> ( $*custom-delimiter = $default-delimiter ) {
}
token foo:sym<c> ( $*custom-delimiter = $default-delimiter ) {
}

Another approach is to have something like:

token pre-foo ( $*custom-delimiter = $default-delimiter ) {
    <foo>
}

In this case an additional method would be required in actions class to propagate $/<foo>.ast one level up.

like image 991
Vadim Belman Avatar asked Nov 15 '18 19:11

Vadim Belman


1 Answers

Based on some test work I've done in one of my modules for allowing scoped settings for a module, you can do this but you will need to use the EXPORT sub.

I imagine the reason is that when doing EXPORT, we can install what is explicitly a brand new dynamic variable, rather than a new symbol linked to an extant dynamic variable — the latter of which to me makes scoping very unclear.

This seems to work okay for me.

# filename: Foo.rakumod
# no 'unit module', etc

sub EXPORT {
  proto token foo {*}
  token foo:a { … }
  token foo:b { … }

  Map.new: 
    '&foo'      => &foo,
    '$*dynamic' => my $ = 'default'
}

like image 86
user0721090601 Avatar answered Oct 30 '22 07:10

user0721090601