Perl 6中的postfix或postcircumfix之前的点是什么意思?

che*_*nyf 13 grammar compilation perl6 postfix-operator raku

在Perl文档中,有一个关于.postfix/.postcircumfix的部分,它说

在大多数情况下,可以在后缀或后缀之前放置一个点:

my @a;
@a[1, 2, 3];
@a.[1, 2, 3]; # Same
Run Code Online (Sandbox Code Playgroud)

从技术上讲,不是真正的运营商; 它的语法特殊于编译器.

我试过自己:

> 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
Run Code Online (Sandbox Code Playgroud)

那么,Perl 6中postfix或postcircumfix之前的点是什么意思呢?它究竟是怎么做到的?我很好奇.谢谢.

Jon*_*ton 15

在Perl 6的表达被解析为termish事情infixish它们之间的事情.A termish又被定义为零或更多的prefixish东西,其次是术语本身,然后是零或更多的postfixish东西.在postfixish所有的需要:

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

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

至于.,语法只是.在a postfix或a 之前接受并忽略a postcircumfix.这是解析器的一个略微缩减的版本,我已经注释了一下来解释它们是什么.

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>
    ]
}
Run Code Online (Sandbox Code Playgroud)

因此,.在这种情况下,根本没有任何意义.解析器只接受它,然后继续寻找它在那一点上真正关心的东西.

值得注意的另一件事是postfix和postcircumfix运算符也可以在一个dotty term之后工作,运行$_.从而:

my @xs = 1..10;
.++ for @xs;
say @xs;
Run Code Online (Sandbox Code Playgroud)

会产生:

[2 3 4 5 6 7 8 9 10 11]
Run Code Online (Sandbox Code Playgroud)

这是postcircumfix示例:

my %h = a => 1, b => 2, c => 3;
say .<a> + .<c> given %h;
Run Code Online (Sandbox Code Playgroud)

哪个产生4.

Perl 6语法通常被设计为使代码从一种形式转移到另一种形式变得容易,并且.即使在不严格需要的地方接受它也会稍微减轻(因此可以重构say %h1.<a> + %h2.<b>;并且解析器可以很好地使用它).学习目的也可能有助于考虑%h<a>做空%h.<a>,这反过来会.<a> given %h让人感到意外.

由此提供的额外空间.也可能有助于清晰,特别是如果要堆叠多个后缀,甚至可以 - 如果语言扩展由于某种原因决定定义一些"有趣"术语或后缀操作符 - 作为消除歧义的手段.