Thank you Richard, for taking time to explain this. I've put comments
below (inline):

On Mon, Aug 5, 2019 at 10:26 AM Richard Hainsworth
<rnhainswo...@gmail.com> wrote:
>
> 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.

Not working for me: the code doesn't return an error but it doesn't
return an answer, either:

mbook:~ homedir$ perl6 -e 'for (lines) { .split(":")[0, 2, 1,
5].join("\t") }' six_fruits1.txt
mbook:~ homedir$

Okay...I see what happened. The ".say" call needs to be added at the end:

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
mbook:~ homedir$

>
> 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.

Okay, same result as earlier: I need to add ".say" at the end to get
any output. I see that a separate "{}" returns nothing, but if I put
the "{}" adjacent to "lines" as in "lines{}" all of a sudden it works
and gives the correct answer. Not only does "lines{}" work, but
"lines()" and "lines[]" works. What doesn't seem to work is a bare
"lines" as noted previously:

mbook:~ homedir$ perl6 -e 'for lines {} { .split(":")[0, 2, 1,
5].join("\t") }' six_fruits1.txt
mbook:~ homedir$ perl6 -e 'for lines {} { .split(":")[0, 2, 1,
5].join("\t").say }' six_fruits1.txt
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
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
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
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 }<EOL>
Missing block (apparently claimed by 'lines')
at -e:1
------> .split(":")[0, 2, 1, 5].join("\t").say }<EOL>


>
> 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.

(I said bare 'lines', not 'bare lines'). But I think I see what you're
saying. First I add the ".say" method below (otherwise i get no
result), then i eliminate everything but { .say} inside the curly
braces. This actually lets me feed an object (for lack of a better
word) into the block:

mbook:~ homedir$ perl6 -e 'for lines () { .split(":")[0, 2, 1,
5].join("\t") }' six_fruits1.txt
mbook:~ homedir$ perl6 -e 'for lines() { .split(":")[0, 2, 1,
5].join("\t") }' six_fruits1.txt
mbook:~ homedir$ perl6 -e 'for lines () { .split(":")[0, 2, 1,
5].join("\t").say }' six_fruits1.txt
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
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
mbook:~ homedir$ perl6 -e 'for lines () { .split(":")[0, 2, 1,
5].join("\t").say }'
mbook:~ homedir$ perl6 -e 'for lines ("a\nb\n") { .split(":")[0, 2, 1,
5].join("\t").say }'
Use of Nil in string context
  in block  at -e line 1
Use of Nil in string context
  in block  at -e line 1
Use of Nil in string context
  in block  at -e line 1
a
Use of Nil in string context
  in block  at -e line 1
Use of Nil in string context
  in block  at -e line 1
Use of Nil in string context
  in block  at -e line 1
b
mbook:~ homedir$ perl6 -e 'for lines ("a\nb\n") { .say }'
a
b
mbook:~ homedir$

Okay. How to express this in simple English? Writing a one-liner "for"
loop for use on a shell command line, you can feed lines into a block
using 'lines()' and adding the target file at the end. Or you can
write "for lines ("line_1\nline_2\n") and then the functions you want
to perform inside the block.

Correct?  Best Regards, Bill.



>
>
> > --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)
> >>>>>>
> >>>>>>

Reply via email to