Perl 6 中后缀或后缀前的点是什么意思?

What does the dot before a postfix or postcircumfix in Perl 6 mean?

在 Perl 文档中,有一节关于 .postfix/.postcircumfix,它说

In most cases, a dot may be placed before a postfix or postcircumfix:

my @a;
@a[1, 2, 3];
@a.[1, 2, 3]; # Same

Technically, not a real operator; it's syntax special-cased in the compiler.

我自己试过:

> my @a = 1,2,3,4,5
> @a[1]  # 2
> @a.[1] # 2

> my %a = Perl => 6, Python => 3, PHP => 7
> %a<Perl>  #6
> %a.<Perl> #6

> my @weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
> @weekdays.antipairs.hash{'Sunday'}  # 6, I expected it to be syntax wrong, but it did work!
> @weekdays.antipairs.hash.{'Sunday'} # 6, seems visual clarity or brevity

那么,Perl 6 中后缀或后缀前的点是什么意思?它到底是怎么做到的?我对此很好奇。谢谢。

Perl 6 中的表达式被解析为 termish 个东西,它们之间有 infixish 个东西。 termish 依次定义为零个或多个 prefixish 事物,后跟术语本身,然后是零个或多个 postfixish 事物。 postfixish 包含所有:

  • 方法调用(如.foo
  • 后缀运算符(如 ++
  • 环后运算符(如 @a[42] 中的 [42]
  • 对这些进行 hyper (>>) 以将它们分布在数据结构中

由于它只是查找其中的零个或多个,因此您可以自由地交错方法调用以及散列和数组索引。这解释了为什么 @weekdays.antipairs.hash{'Sunday'} 可以很好地解析(以及为什么 @weekdays.antipairs.hash<Sunday> 也可以,甚至 @weekdays.antipairs.hash<Sunday>.say 也可以)。

至于 .,语法简单地接受并忽略 postfixpostcircumfix 之前的 .。这是解析器的一个稍微精简的版本,我已经做了一些注释来解释这些部分是什么。

token postfixish {
    <!stdstopper>

    # If we're not in a string interpolation, allow unspace (that's
    # where you write `\      ++`, for example, allowing spreading
    # postfixish things over multiple lines).
    [ <!{ $*QSIGIL }> [ <.unsp> | '\' ] ]?

    # Here we match the >> for doing a hyper. Note that it accepts
    # but disregards a '.' before it. It's not captured at all and
    # doesn't affect the code that is compiled.
    [ ['.' <.unsp>?]? <postfix_prefix_meta_operator> <.unsp>?]**0..1

    [
    | <OPER=postfix>
    # When there'd be no confusion with a method call, a '.' is
    # also accepted and disregarded before a postfix operator
    | '.' <?before \W> <OPER=postfix>  ## dotted form of postfix operator (non-wordy only)
    | <OPER=postcircumfix>
    # Ditto here for recognized postcircumfixes
    | '.' <?[ [ { < ]> <OPER=postcircumfix>
    | <OPER=dotty>
    | <OPER=privop>
    ]
}

因此 . 在这种情况下毫无意义。解析器简单地接受它,然后继续寻找它当时真正关心的东西。

另一件值得注意的事情是 postfix 和 postcircumfix 运算符也都在 dotty term 之后工作,在 $_ 上运行。因此:

my @xs = 1..10;
.++ for @xs;
say @xs;

将产生:

[2 3 4 5 6 7 8 9 10 11]

这是一个后置环路示例:

my %h = a => 1, b => 2, c => 3;
say .<a> + .<c> given %h;

产生 4.

Perl 6 语法通常旨在使代码从一种形式转换为另一种形式变得容易,并且在一些地方接受 . 即使不是严格需要它也可以稍微简化一点(因此可以重构为say %h1.<a> + %h2.<b>; 并且解析器会很好)。将 %h<a> 视为 %h.<a> 的缩写也可能有助于学习,这反过来会使 .<a> given %h 不那么令人惊讶。

. 提供的额外 space 也可能有助于清晰度,特别是如果要堆叠多个后缀,甚至可能 - 如果语言扩展出于某种原因决定定义一些 "interesting" 术语或后缀运算符 - 作为消除歧义的手段。

当你有一个 returns 一个 Callable.

的子时,它实际上很重要
sub foo { 'hello' }
sub bar { &foo; }
bar.WHAT # (Sub)
bar().WHAT # (Sub)
bar.().WHAT # (Str)
bar()().WHAT # (Str)
bar().().WHAT # (Str)
bar.().().WHAT # No such method 'CALL-ME' for invocant of type 'Str'