William,
I saw others were replying and between what Brad had said and what I had
said, I thought the explanations were pretty clear.
So I'll try again.
Comments in text below.
On 03/08/2019 07:11, William Michels wrote:
Hi Richard, I'm not able to come to the same conclusions.
Specifically, the previous code examples starting with 'for lines()'
always have to have parentheses following 'lines' (as in 'lines()
{...}'), otherwise Perl_6 balks (examples 6 and 7 previously posted).
This is whether 'information is being passed' or not (i.e. empty
parentheses are required):
#example 6:
mbook:~ homedir$ perl6 -e ' for lines() { say .split(":")[0, 2, 1,
5].join("\t") };' six_fruits1.txt
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
#example 6 no-parens:
mbook:~ homedir$ perl6 -e ' for lines { say .split(":")[0, 2, 1,
5].join("\t") };' six_fruits1.txt
===SORRY!===
Function 'lines' needs parens to avoid gobbling block
at -e:1
------> say .split(":")[0, 2, 1, 5].join("\t") };
Missing block (apparently claimed by 'lines')
at -e:1
------> say .split(":")[0, 2, 1, 5].join("\t") };
It seems to me that the error message is quite clear. Perl 6 knows
'lines' can take something following it, and it is expecting to get a
list which can be interpreted as lines to act upon. But then 'for' has
nothing to work on. Perl6 has figured out that you actually want the
block to go with the 'for' and not 'lines', but since there is an
ambiguity, Perl 6 errors out, and tells you what the probable mistake is.
It has nothing to do with whether 'lines' needs () or not, but to do
with writing unambiguous code. Rather than writing 'lines()', which
personally I find distasteful, I would write:
perl6 -e '.split(":")[0,2,1,5].join("\t").say for lines' six_fruits1.txt
'lines' has no () , in your words 'is bare'. But this code is
unambiguous because it is clear that `.split` etc will take the topic
(aka $_) from the 'for' and 'lines' takes its data from @_, which is
provided from the file.
#example 7:
mbook:~ homedir$ perl6 -e 'for lines() {.split(":")[0, 2, 1,
5].join("\t").say};' six_fruits1.txt
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
#example 7 no-parens:
mbook:~ homedir$ perl6 -e 'for lines {.split(":")[0, 2, 1,
5].join("\t").say};' six_fruits1.txt
===SORRY!===
Function 'lines' needs parens to avoid gobbling block
at -e:1
------> {.split(":")[0, 2, 1, 5].join("\t").say};
Missing block (apparently claimed by 'lines')
at -e:1
------> {.split(":")[0, 2, 1, 5].join("\t").say};
Same explanation as before. There is no difference between `say .split`
etc in your example 6, and `.split ... .say` in example 7. So the
problem you are running into has nothing to do with chaining .say or
using say as a sub.
mbook:~ homedir$ perl6 --version
This is Rakudo version 2019.07.1 built on MoarVM version 2019.07.1
implementing Perl 6.d.
mbook:~ homedir$
Other Perl_6 users have replied with a general discussion of
differences between using lines() as a method, or in a subroutine. I
still have to review some of those comments. However, as I'm using the
latest Perl_6 version (2019.07.1), I'm fairly confident in the results
above (and below).
Also, the examples below show that 'for lines[0..2] {...}' works,
despite the previous error message insisting on parentheses ("Function
'lines' needs parens to avoid gobbling block at -e:1"). Taken
together, the results above and below seem to indicate to me that the
use of a bare 'lines' sub is disallowed, at least in a 'for' loop.
Nope. What is disallowed is a bare 'lines' sub in an ambiguous context.
The idiom 'for lines { .say }' is ambiguous because
the '{ .say }' has to be given to 'lines', but you want it to be given
to 'for'. And the reason for that choice of syntax was explained by Brad.
This works:
perl6 -e 'for ( lines ) { .split(":")[0, 2, 1, 5].join("\t") }'
six_fruits1.txt
'lines' is bare, but the brackets disambiguate the block from 'lines' .
Personally, I think this is also somewhat ugly.
The following 'bare lines with a for' also 'works' in that no errors are
generated (Perl 6 does not disallow bare 'lines' with a for), but there
is no output so it doesn't give the desired output.
perl6 -e 'for lines {} { .split(":")[0, 2, 1, 5].join("\t") }'
six_fruits1.txt
Obviously, 'lines' has been given something to operate on, and in this
case it is interpreted not as a block, but an empty hash. And since
'lines' had been given an explicit argument, Perl 6 did not know to
provide the data from six_fruits1.txt to anything, so the data was ignored.
Almost the same thing, note the space between 'lines' and '()':
perl6 -e 'for lines () { .split(":")[0, 2, 1, 5].join("\t") }'
six_fruits1.txt
Here, 'lines' is given an empty list, viz. ' ()', the preceding space
telling Perl 6 that '()' is a list, not a signature
However, "bare lines" is not "disallowed" for a 'for'.
Hope this helps.
--Best Regards, Bill.
#example 10:
mbook:~ homedir$ perl6 -e 'for lines { say .split(":")[0, 2, 1,
5].join("\t") };' six_fruits1.txt
===SORRY!===
Function 'lines' needs parens to avoid gobbling block
at -e:1
------> say .split(":")[0, 2, 1, 5].join("\t") };
Missing block (apparently claimed by 'lines')
at -e:1
------> say .split(":")[0, 2, 1, 5].join("\t") };
#example 11:
mbook:~ homedir$ perl6 -e 'for lines() { say .split(":")[0, 2, 1,
5].join("\t") };' six_fruits1.txt
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
#example 12:
mbook:~ homedir$ perl6 -e 'for lines[0..2] { say .split(":")[0, 2, 1,
5].join("\t") };' six_fruits1.txt
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
On Fri, Aug 2, 2019 at 1:20 AM Richard Hainsworth
<rnhainswo...@gmail.com> wrote:
Not quite sure what sort of "rule" you want.
You used () and [] which do different things and the results were exactly what
I would expect. They are covered in the documentation. Basically, () without a
space, eg xxxx() not xxxx (), is used to pass information to the sub or method
xxxx.
If no information is being passed, then no need to use (). The way xxxx
responds to no data provided depends on the way xxxx is written. The programmer
could provide default values for the arguments it expects. Perl6 also makes the
value of the default variable, eg $_, to xxxx.
If you put a space between xxxx (), then () is interpreted as an empty list and
provide to xxxx as a single piece of information.
[] Are used to dereference a list (sequence or array, they are all slightly
different).
I'll comment more below. Sometimes I think through the process using slightly
different and less exact words. My comments are illustrative.
On Fri, 2 Aug 2019, 04:50 William Michels, <w...@caa.columbia.edu> wrote:
Hi Richard, I'm trying to figure out when the parentheses in 'lines()'
can be dropped, and 'lines' used instead. Any pointers? I have about
nine or so working examples below, but formulating a clear
rule-of-thumb is proving elusive. Any help appreciated, --Best, Bill.
# test file: six_fruits1.txt
mbook:~ homedir$ cat six_fruits1.txt
apple:banana:carrot:dragonfruit:eggplant:favabean
apricot:basil:cabbage:dill:escarole:fennel
acai:beets:celery:daikon:endive:figs
mbook:~ homedir$ perl6 -e '.say for lines()' six_fruits1.txt
apple:banana:carrot:dragonfruit:eggplant:favabean
apricot:basil:cabbage:dill:escarole:fennel
acai:beets:celery:daikon:endive:figs
Here 'lines ()' is the same as 'lines'.
The program in the string after -e is provided with the data inside the file.
mbook:~ homedir$ perl6 -e '.say for lines' six_fruits1.txt
apple:banana:carrot:dragonfruit:eggplant:favabean
apricot:basil:cabbage:dill:escarole:fennel
acai:beets:celery:daikon:endive:figs
The top two are equivalent
mbook:~ homedir$ perl6 -e '.say for lines("a\nb\n")' six_fruits1.txt
a
b
Here you provided data to 'lines' which it was able to interpret as a set of
lines. So it printed them. The data in six_fruits is ignored because you
provided the data explicitly.
mbook:~ homedir$ perl6 -e '.say for lines[0]' six_fruits1.txt
apple:banana:carrot:dragonfruit:eggplant:favabean
Six_fruits has 3 lines. Lines has processed the data. But you wrote '[0]' which
extracted the first line, and that was processed by the 'for' loop. In other
words the 'for' was only given one piece of information to process.
mbook:~ homedir$ perl6 -e '.say for lines[0..1]' six_fruits1.txt
apple:banana:carrot:dragonfruit:eggplant:favabean
apricot:basil:cabbage:dill:escarole:fennel
The '[0..1]' extracts the first three pieces of data from 'lines' and they are
processed by the 'for'
mbook:~ homedir$ perl6 -e ' for lines() { say .split(":")[0, 2, 1,
5].join("\t") };' six_fruits1.txt
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
Could be just 'lines', which provides a list of the lines in the file to the
'for'
Inside the 'for' the data is in the topic or default variable. You could access
it as $_ but '.split' accesses it automatically. Split generates another list.
'[0,2,1,5]' extracts the relevant elements of the list and generates another
list which is passed to the'join'. The output from join is passed to 'say'
which is written in sub form. Sub form means you write the name of the sub
first, then you write where the data is coming from.
mbook:~ homedir$ perl6 -e ' for lines() {.split(":")[0, 2, 1,
5].join("\t").say};' six_fruits1.txt
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
Exactly the same for perl6 as before except that 'say' is written in sub form
above and in method form here. Method form means you can append the 'say' to a
chain of processing units.
mbook:~ homedir$ perl6 -e 'for "six_fruits1.txt".IO.lines()
{.split(/\:/)[0, 2, 1, 5].join("\t").say};'
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
Here just accessing the data in the file explicitly in perl6.
mbook:~ homedir$ perl6 -e 'for "six_fruits1.txt".IO.lines
{.split(/\:/)[0, 2, 1, 5].join("\t").say};'
apple carrot banana favabean
apricot cabbage basil fennel
acai celery beets figs
Same as above. No () on lines
On Mon, Jul 29, 2019 at 1:07 AM Richard Hainsworth
<rnhainswo...@gmail.com> wrote:
Also no need for all the brackets
.say for lines;
This is quite idiomatic Perl 6 and not golfing
On Mon, 29 Jul 2019, 07:13 Joseph Brenner, <doom...@gmail.com> wrote:
Hmmm. I would expect that to be in the Perl 5 to Perl 6 Migration Guides, but I
do not see it there.
Exactly, I was just looking there, and I ended up playing around with
the method form of lines, and didn't think to try the function
form of it.
To summarize, if the goal is to write a "simple_echo" script that
can work with a file name or with lines on standard input:
simple_echo lines.txt
cat lines.txt | simple_echo
The perl5 version would probably be:
#!/usr/bin/env perl
while(<>){
print;
}
The perl6 version would be something like:
#!/usr/bin/env perl6
use v6;
for lines() {
say $_;
}
The kind of thing I was playing with was:
#!/usr/bin/env perl6
use v6;
my @lines = $*ARGFILES.IO.lines;
say @lines;
That works for lines from a file, but not from standard input, and the
error message isn't tremendously helpful:
No such method 'lines' for invocant of type 'IO::Special'
On 7/28/19, Bruce Gray <robertbrucegr...@gmail.com> wrote:
On Jul 28, 2019, at 6:20 PM, Joseph Brenner <doom...@gmail.com> wrote:
I was just wondering if there's some direct analog in perl6 to the
perl5 construct:
while(<>){ ... }
If I'm planning on passing a filename on the command-line, I can just
get it out of $*ARGFILES easily enough, but what if I also wanted it
to work on lines passed in via standard input?
`lines` , as a sub instead of a method, and no arguments.
See: https://docs.perl6.org/routine/lines#(Cool)_routine_lines
Without any arguments, sub lines operates on $*ARGFILES, which defaults
to
$*IN in the absence of any filenames.
For example:
perl6 -e 'say .join("\t") for lines().rotor(4);' path/to/file.txt
Hmmm. I would expect that to be in the Perl 5 to Perl 6 Migration Guides,
but I do not see it there.
—
Hope this helps,
Bruce Gray (Util of PerlMonks)