Why is this Perl 6 feed operator a “bogus statement”?

余生颓废 提交于 2019-12-09 03:13:06

问题


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"?


回答1:


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.



来源:https://stackoverflow.com/questions/45269484/why-is-this-perl-6-feed-operator-a-bogus-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!