为什么这个 Perl 6 feed 操作符是一个“虚假声明"? [英] Why is this Perl 6 feed operator a "bogus statement"?

查看:50
本文介绍了为什么这个 Perl 6 feed 操作符是一个“虚假声明"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从 第 10 天 - Feed 操作员中获取了这个示例Perl 6 2010 Advent Calendar 中的 .uc 略有更改,.ucfirst 不再存在:

我的@rakudo-people = ;@乐堂人==>grep {/at/} ==>地图 { .uc } ==>我的@who-it's-at;说~@who-it's-at;

我用一些额外的空格来写它:

我的@rakudo-people = ;@乐堂人==>grep {/at/}==>地图 { .uc } ==>我的@who-it's-at;说~@who-it's-at;

现在是虚假陈述":

<块引用>

===SORRY!=== 编译时出错...虚假陈述------>==>grep {/at/}⏏期待以下任何一项:后缀字首语句结束学期

仅此示例就没有问题.当前文档中的一些示例可以表现出相同的行为.

如果我在违规行的末尾添加 unspace,它会起作用再次:

我的@rakudo-people = ;@乐堂人==>grep {/at/} \==>地图 { .uc } ==>我的@who-it's-at;说~@who-it's-at;

奇怪的是,该行末尾的注释不起作用.我原以为它会吃掉有问题的空白.

feed 运营商 说:

<块引用>

对于采用单个参数或第一个参数是块的例程/方法,通常需要使用括号进行调用

那行得通:

我的@rakudo-people = ;@乐堂人==>grep( {/at/} )==>地图 { .uc } ==>我的@who-it's-at;说~@who-it's-at;

但是为什么在第一种形式中这不是问题?空白在这里做什么?经常需要"包括哪些情况?

解决方案

来自关于分隔语句的 Perl 6 文档:

<块引用>

右花括号后跟换行符表示语句分隔符

换句话说,只要块的右大括号是一行中的最后一个东西(不包括空格和注释),解析器就会在它后面隐式插入一个分号.

这允许我们在 } 后不加分号的情况下编写如下内容:

my @foo = @bar.map: {...}

分号在那里会很丑,如果你先把循环写成 for @bar { ... } 然后决定把它变成一个 map像这样的分配,添加尾随分号会很烦人,很容易忘记.所以在大多数情况下,这种在行尾块之后自动终止语句是有帮助的.

但是,喂食块的饲料运营商是一种(可能是唯一一种)让人们绊倒的情况.

为了防止它发生,插入 \(又名 unspace) 在块之后,正如您已经注意到的.unspace 使包含换行符的空白对解析器不可见,因此不会应用上述基于换行符的解析器规则.

I took this example from Day 10 – Feed operators of the Perl 6 2010 Advent Calendar with the slight change of .uc for the .ucfirst that's no longer there:

my @rakudo-people = <scott patrick carl moritz jonathan jerry stephen>;
@rakudo-people
    ==> grep { /at/ } ==> map { .uc } ==> my @who-it's-at;
say ~@who-it's-at;

I write it slightly differently with some additional whitespace:

my @rakudo-people = <scott patrick carl moritz jonathan jerry stephen>;
@rakudo-people
    ==> grep { /at/ }
    ==> map { .uc } ==> my @who-it's-at;
say ~@who-it's-at;

Now it's a "bogus statement":

===SORRY!=== Error while compiling ...
Bogus statement
------>         ==> grep { /at/ }⏏<EOL>
expecting any of:
    postfix
    prefix
    statement end
    term

This isn't a problem with just this example. Some examples in the current docs can exhibit the same behavior.

If I add an unspace to the end of the offending line, it works again:

my @rakudo-people = <scott patrick carl moritz jonathan jerry stephen>;
@rakudo-people
    ==> grep { /at/ } \
    ==> map { .uc } ==> my @who-it's-at;
say ~@who-it's-at;

Curiously, a comment at the end of that line does not work. I would have thought it would have eaten the offending whitespace.

The feed operator says:

In the case of routines/methods that take a single argument or where the first argument is a block, it's often required that you call with parentheses

That works:

my @rakudo-people = <scott patrick carl moritz jonathan jerry stephen>;
@rakudo-people
    ==> grep( { /at/ } )
    ==> map { .uc } ==> my @who-it's-at;
say ~@who-it's-at;

But why wasn't that a problem in the first form? What is the whitespace doing here? And what situations are included in "often required"?

解决方案

From the Perl 6 documentation on Separating Statements:

A closing curly brace followed by a newline character implies a statement separator

In other words, whenever the closing brace of a block is the last thing in a line (not counting whitespace and comments), then the parser implicitly inserts a semicolon after it.

This allows us to write things like the following without a semicolon after the }:

my @foo = @bar.map: {
    ...
}

The semicolon would be ugly there, and if you had first written the loop as for @bar { ... } and then decided to turn it into a map with assignment like this, adding the trailing semicolon would be annoying and easy to forget. So for the most part, this automatic statement termination after end-of-line blocks is helpful.

However, feed operators feeding into blocks are one case (possibly the only one) where it trips people up.

To prevent it from happening, insert \ (a.k.a. unspace) after the block, as you've already noted. The unspace makes the whitespace which includes the newline invisible to the parser, and thus the aforementioned newline-based parser rule won't be applied.

这篇关于为什么这个 Perl 6 feed 操作符是一个“虚假声明"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆