代码之家  ›  专栏  ›  技术社区  ›  chenyf

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

  •  15
  • chenyf  · 技术社区  · 7 年前

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

    在大多数情况下,点可以放在后缀或后圆圈之前:

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

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

    我试过自己:

    > 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中后缀或后循环前的点是什么意思?它究竟是怎么做到的?我对此很好奇。谢谢

    2 回复  |  直到 6 年前
        1
  •  16
  •   Toby Speight    7 年前

    Perl 6中的表达式解析为 termish 与…相关的东西 infixish 他们之间的事情。A. 白蚁 依次定义为零或更多 prefixish 事物,后跟术语本身,后跟零或更多 postfixish 事情。这个 后固定 包含所有:

    • 方法调用(如 .foo )
    • 后缀运算符(如 ++ )
    • Postcircumfix操作符(如 [42] 在里面 @a[42] )
    • 正在执行hyper( >> )将它们分布在数据结构上

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

    至于 . ,语法只接受并忽略 在a之前 postfix 或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>
        ]
    }
    

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

    另一件值得注意的事情是,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 少一点惊喜。

    提供的额外空间 也可能有助于澄清,尤其是在要堆叠多个后缀的情况下,如果语言扩展出于某种原因决定定义一些“有趣的”术语或后缀运算符,甚至可以作为消除歧义的手段。

        2
  •  2
  •   Tusooa Windy    7 年前

    当你有一个返回 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'
    
    推荐文章