Экспорт динамически изменяемых переменных?
По сути, вопрос скорее в грамматике, но я думаю, что это может быть более интересным упражнением по динамическим переменным.
У меня есть роль грамматики с прототипом токена (пример упрощен, чтобы продемонстрировать идею):
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)>
}
Когда роль поглощена грамматикой, я хочу $*custom-delimiter
быть установленным грамматикой. Конечно, я могу объявить это везде, где <foo>
нужно. Но иногда можно предварительно инициализировать его универсальным значением по умолчанию. Что-то вроде:
{ $*custom-delimiter //= $default-delimiter }
в value
маркер будет работать. Но внешняя предварительная декларация все еще была бы необходима.
Я надеялся, что:
our $*custom-delimiter is export = $default-delimiter;
в объеме модуля, где объявлена роль будет работать. Но, видимо, это не так. Итак, вопрос: есть ли элегантные решения для этого?
На самом деле, я также надеюсь, что решение позволит перенести декларацию $*delimiter
в foo
вне определения токена тоже.
В качестве примечания: моя первая мысль была о добавлении параметра в токен. Но иметь абсолютно одинаковые подписи для каждого варианта тоже выглядит ужасно:
token foo:sym<a> ( $*custom-delimiter = $default-delimiter ) {
}
token foo:sym<b> ( $*custom-delimiter = $default-delimiter ) {
}
token foo:sym<c> ( $*custom-delimiter = $default-delimiter ) {
}
Другой подход - иметь что-то вроде:
token pre-foo ( $*custom-delimiter = $default-delimiter ) {
<foo>
}
В этом случае потребуется дополнительный метод в классе действий для распространения $/<foo>.ast
на один уровень выше.
0 ответов
Основываясь на некоторой тестовой работе, которую я проделал в одном из моих модулей, чтобы разрешить настройки с заданной областью для модуля, вы можете это сделать, но вам нужно будет использовать подгруппу EXPORT.
Я предполагаю, что причина в том, что при выполнении EXPORT мы можем установить то, что является явно новой динамической переменной, а не новым символом, связанным с существующей динамической переменной - последнее из которых для меня очень неясно.
Мне кажется, это работает нормально.
# 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'
}