基本上,问题更多是关于语法,但我认为这可能是关于动态变量的更有趣的练习。
我有一个带有原型标记的语法角色(示例被简化以演示该思想):
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 :(得分:1)
基于我在一个模块中所做的一些测试工作,以允许对模块进行范围设置,您可以执行此操作,但是您将需要使用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'
}