这是两个语法.一个使用a proto token
而一个不使用.他们都完成了同样的事情.这些基本上是"变量(非)插值"下的S05中的示例.在这个简单的例子中,他们都能够做同样的事情.
哪种情况证明所有额外的打字?该proto
令牌在动作类不同的方法,也许有一个小的好处在那里.但是,您必须输入一些额外的东西才能获得这些好处.
是否有一些功能proto
使语法的其他部分更容易?
grammar NoProto { token variable {} token identifier { + } token sigil { < $ @ % & :: > } } grammar YesProto { token variable { } token identifier { + } proto token sigil { * } token sigil:sym<$> { } token sigil:sym<@> { } token sigil:sym<%> { } token sigil:sym<&> { } token sigil:sym<::> { } } class Proto::Actions { method variable ($/) { say "found variable: " ~ $/; } method identifier ($/) { say "found identifier: " ~ $/; } method sigil ($/) { say "found sigil: " ~ $/; } method sigil:sym<$> ($/) { say "found sym sigil: " ~ $/; } } my $variable = '$butterfuly'; say "------No proto parsing"; my $no_proto_match = NoProto.parse( $variable, :rule , :actions(Proto::Actions), ); say "------Yes proto parsing"; my $yes_proto_match = YesProto.parse( $variable, :rule , :actions(Proto::Actions), );
输出显示proto
在action类中调用不同的方法:
------No proto parsing found sigil: $ found identifier: butterfuly found variable: $butterfuly ------Yes proto parsing found sym sigil: $ found identifier: butterfuly found variable: $butterfuly
Elizabeth Ma.. 9
从技术上讲,proto
如果您没有自己指定,将为您制作.它基本上会为特别多方法分派处理程序token
(就像它与不sub
和method
).你通常不需要关心.
你为什么要指定一个proto
?我可以想到很多原因:
因为你想让token
s分享一些特质
因为你想在发送之前或之后执行一些代码
是的,{ * }
可能包含可执行代码.裸Whatever
表示向适当的候选人发送.在更简单的情况下显示这个sub
:
proto a(|) { say "before"; {*}; say "after" } multi a(Int) { say "Int" } multi a(Str) { say "Str" } a 42; a "42"
说明:
before Int after before Str after
希望这可以帮助 :-)
从技术上讲,proto
如果您没有自己指定,将为您制作.它基本上会为特别多方法分派处理程序token
(就像它与不sub
和method
).你通常不需要关心.
你为什么要指定一个proto
?我可以想到很多原因:
因为你想让token
s分享一些特质
因为你想在发送之前或之后执行一些代码
是的,{ * }
可能包含可执行代码.裸Whatever
表示向适当的候选人发送.在更简单的情况下显示这个sub
:
proto a(|) { say "before"; {*}; say "after" } multi a(Int) { say "Int" } multi a(Str) { say "Str" } a 42; a "42"
说明:
before Int after before Str after
希望这可以帮助 :-)
在动作类中调用它的方法对于分离逻辑非常有用.除了语法之外,它基本上与多方法相同.
(我写这篇文章是为了评估Code Golf的答案)
grammar Mathemania {
token TOP { }
token cmd-list { + }
token cmd { ? }
proto token op { * }
token op:sym { e } # notice that the name doesn't have to match
token op:sym { f }
token op:sym { r }
token op:sym { c }
token op:sym { l }
token argument { '(' ~ ')' }
}
class Calculate {
method TOP ($/) { make $.made }
method argument ($/) { make $.made }
method cmd-list ($/) {
my $result = 2;
$result = .made.($result).narrow for @;
make $result;
}
method cmd ($/) {
if $ {
make $.made.assuming( *, $.made );
} else {
make $.made;
}
}
method op:sym ($/) { make -> \n, \e = 2 { n ** e } }
method op:sym ($/) { make -> \n, \k = 2 { [*] n, n - k + 1 ...^ 0 } }
method op:sym ($/) { make -> \n, \r = 2 { n ** (1/r) } }
method op:sym ($/) { make &ceiling }
method op:sym ($/) { make &floor }
}
它还使得子类化语法可以将其标记与已存在的标记一起添加,并且子类化动作类可以执行相同的操作.(试试吧)
grammar Mathmania-Plus is Mathemania {
token op:sym { n }
token op:sym { a }
}
class Calculate-Plus is Calculate {
method op:sym ($/) { make &prefix:<-> }
method op:sym ($/) { make &abs }
}
将您的替代品拆分为proto和multis的一个好处是您可以更可靠地扩展它.您可以在语法中将multis添加到语法中,该语法继承自声明proto的语法,并且您不需要列出所有可能的替代项(如果是单个规则,则必须执行此操作).
这意味着您甚至可以对同一语法进行多个独立扩展,例如通过混合使用多个规则来为不同的符号提供匹配.
这基本上是Perl 6在定义自定义运算符时使用的机制:有匹配不同类型运算符的规则(如中缀,前缀,后缀,...),并声明新运算符从中派生新语法当前活动的一个,为新运算符添加了多个候选项.由于proto令牌机制的可扩展性,脚本可以从几个彼此不了解的模块中导入操作符.