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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With