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



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

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

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

由于它只查找零个或多个,因此您可以自由交错方法调用以及哈希和数组索引。这就解释了为什么@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>
]
}

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

另一件值得注意的事情是,后缀和后环固定运算符也都在一个小项之后工作,在$_上运行。因此:

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少一点惊喜。

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

当你有一个返回Callable的 sub 时,这实际上很重要。

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'

最新更新