Raku 中的 Superscripts

Superscripts in Raku

Raku 中的 Superscripts

在 Raku 中,可以使用上标索引来计算数字的幂数,例如:

> 2⁵
32

> 7³
343

也可以在上标中使用多个数字:

> 10¹²
1000000000000

你可以猜到,上面的代码等同于这样:

> 2**5
32
> 7**3
343

> 10**12
1000000000000

但问题是:上标到底是如何工作的?让我们找出答案。

对于 Numeric 角色,定义了以下操作:

proto sub postfix:<ⁿ>(Mu $, Mu $) is pure {*}
multi sub postfix:<ⁿ>(\a, \b) { a ** b }

啊哈,这就是我们需要的,上标符号在这里转换为简单的 ** 运算符。

您可以通过打印操作数来可视化传递给操作的确切内容:

multi sub postfix:<ⁿ>(\a, \b) {
    nqp::say('# a = ' ~ a);
    nqp::say('# b = ' ~ b);
    a ** b
}

这个时候,你会看到上面的测试示例输出如下:

> 2⁵
# a = 2
# b = 5

> 10¹²
# a = 10
# b = 12

现在,是时候理解提取上标的后缀是如何工作的了。它的名字 用上标写成,不应误导你。这不是解析器的魔术,这只是符号的名称,它可以在 Grammar 中找到:

token postfix:sym<ⁿ> {
    <sign=[⁻⁺¯]>? <dig=[⁰¹²³⁴⁵⁶⁷⁸⁹]>+ <O(|%autoincrement)>
}

你看,这个符号是一系列的上标数字,在它们之前有一个可选的符号。 (在 Grammar 到达这个时刻之前,你有没有想到过一个标志?)

顺便说一下,我们可以试试负数作为幂:

> say 4⁻³
# a = 4
# b = -3
0.015625

另请注意,整个构造被视为后缀运算符。它也可以应用于变量,例如:

> my $x = 9
9
> say $x²
# a = 9
# b = 2
81

所以,上标中的数字不是变量名称的一部分。

好的,三部曲的最后一部分,是解析索引的 Actions 代码:

method postfix:sym<ⁿ>($/) {
    my $Int := $*W.find_symbol(['Int']);
    my $power := nqp::box_i(0, $Int);
    for $<dig> {
        $power := nqp::add_I(
           nqp::mul_I($power, nqp::box_i(10, $Int), $Int),
           nqp::box_i(nqp::index("⁰¹²³⁴⁵⁶⁷⁸⁹", $_), $Int),
           $Int);
    }

    $power := nqp::neg_I($power, $Int)
        if $<sign> eq '⁻' || $<sign> eq '¯';
    make QAST::Op.new(:op<call>, :name('&postfix:<ⁿ>'),
                      $*W.add_numeric_constant($/, 'Int', $power));
}

正如你在这里看到的那样,它扫描数字并通过在下一个小数位上添加值(在上面的代码中选择它)来更新 $power 变量。

可用字符在一个字符串中列出,为了得到它的值,使用字符串中的偏移量。 $<dig> match 包含一个数字,您可以在 Grammar 中看到它:

<dig=[⁰¹²³⁴⁵⁶⁷⁸⁹]>+

comments powered by Disqus