raku grammar 中的冒号对儿

欢迎来到这个系列的第 50 篇文章!

今天, 我们将讨论一个小的语法结构, 然而就 Grammar 来说这是非常复杂的。首先让我们看看整个 colonpair token:

token colonpair {
    :my $*key;
    :my $*value;

    ':'
    :dba('colon pair')
    [
    | '!' [ <identifier> || <.panic: "Malformed False pair; expected identifier"> ]
        [ <[ [ ( < { ]> {
        $/.typed_panic('X::Syntax::NegatedPair', key => ~$<identifier>) } ]?
        { $*key := $<identifier>.Str; $*value := 0 }
    | $<num> = [d+] <identifier> [ <?before <.[ [ ( < { ]>> {} <.sorry("Extra argument not allowed; pair already has argument of " ~ $<num>.Str)> <.circumfix> ]?
        <?{
            . . . # Some NQP things happen here, refer to the code if needed
        }>
        { $*key := $<identifier>.Str; $*value := nqp::radix_I(10, $<num>, 0, 0, $*W.find_symbol(['Int']))[0]; }
    | <identifier>
        { $*key := $<identifier>.Str; }
        [
        || <.unsp>? :dba('pair value') <coloncircumfix($*key)> { $*value := $<coloncircumfix>; }
        || { $*value := 1; }
        ]
    | :dba('signature') '(' ~ ')' <fakesignature>
    | <coloncircumfix('')>
        { $*key := ""; $*value := $<coloncircumfix>; }
    | <var=.colonpair_variable>
        { $*key := $<var><desigilname>.Str; $*value := $<var>; self.check_variable($*value); }
    ]
}

token 总是从冒号开始匹配。那么, 有六个主要的备选分支。让我们简单介绍一下他们的前半部分。

每个分支以赋值给两个动态变量 $key$value 结束。

1

当您想要传递 False 值作为命名参数时使用第一个变体, 例如:

sub f($x, :$print = 1) {
    say $x if $print;
}

f(3);          # 3
f(4, :!print); # nothing

如果不将 :$print 命名参数设置为 False 值, 则此函数将打印其第一个参数。在 Raku 中, 这可以使用快捷方式 :!print 完成。因此, 在第二次调用中, 该函数不会打印任何内容。

2

token 的第二个分支用于传递数值的特殊形式。检查以下代码片段:

sub g(:$value) {
    say $value;
}

g(:10value); # 10

一个函数接受一个命名参数, 并且你可以以一种奇怪的格式 :10value 传递它的值, 这意味着使 :$value 值的值等于 10

3

第三个选项可能是使用冒号语法的最常用方法。以下示例触发此分支:

sub g(:$value) {
    say $value;
}

g(:value(10)); # 10

这与前一节中的功能相同, 但值的传递方式不同。

当您需要与第一个相反时, 也使用此选项。在这种情况下, 您使用命名参数作为布尔标志并将其值设置为 True。下一个例子表明:

sub h(:$value) {
    say $value;
}

h(:value); # True

请注意, 如果您使用感叹号否定它(在这种情况下, token 的第一个分支起作用), 则 value 的值为 False:

h(:!value); # False