8

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

Christopher Bottoms
  • 11,218
  • 8
  • 50
  • 99
brian d foy
  • 129,424
  • 31
  • 207
  • 592

1 Answers1

11

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.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
smls
  • 5,738
  • 24
  • 29