On Mon, 19 Feb 2018 19:48:30 -0800, c...@zoffix.com wrote:
> On Mon, 19 Feb 2018 16:15:37 -0800, comdog wrote:
> > #!/Users/brian/bin/perl6s/perl6-latest
> >
> > I'm playing with .next-handle from IO::CatHandle. I'm
> > trying to create a situation where I can read just the first five
> > lines from each command line argument:
> >
> > quietly {
> >     my $limit = 5;
> >     for lines() {
> >         state $lines = 1;
> >         FIRST { $*ARGFILES.on-switch = { put "NEW FILE"; $lines = 1 }
> > }
> >         if $lines > $limit {
> >             $*ARGFILES.next-handle;
> >             next;
> >             }
> >         put "{$*ARGFILES.path}:{$lines++} $_";
> >         }
> >     }
> >
> > Here's a test file:
> >
> > First
> > Second
> > Third
> > Fourth
> > Fifth
> > Six
> > Seventh
> >
> > With one or more command-line arguments I get this odd behavior (and
> > lots of warnings that I suppressed):
> >
> > test.txt:1 First
> > test.txt:2 Second
> > test.txt:3 Third
> > test.txt:4 Fourth
> > test.txt:5 Fifth
> > NEW FILE
> > :1 Seventh
> > read bytes requires an object with REPR MVMOSHandle (got VMNull
> > with REPR Null)
> >   in block <unit> at lines-method.p6 line 5
> >
> > It does "switch" after five lines, but then it keeps reading from the
> > same handle while losing a line. Then there's a strange error at the
> > end that kills the whole thing.
> >
> > I expected that it would close the current handle, open a new one,
> > and
> > continue. If it gets to the end, it would simply not provide any more
> > lines() and things would end normally.
> >
> > The docs for .next-handle lets you keep changing it as long as you
> > like no matter how many
> >
> > -----
> >
> > This is Rakudo Star version 2018.01 built on MoarVM version 2018.01
> > implementing Perl 6.c.
> 
> 
> This is because current implementation of IO::CatHandle.lines simply
> flattens
> a gather/taken .lines Seq from each handle, so it never expects the
> handles to
> get switched before each .lines Seq is fully-consumed. The .next-
> handle closes
> the previous handle, which is where the weird error comes from (it
> tries to use
> the now-nulled $!PIO to .read/.eof from). Pretty sure .words is
> similarly affected.
> 
> I think if we give IO::CatHandle!LINES and IO::CatHandle!WORDS their
> own
> iterators that basically do the same thing as IO::Handle ones and then
> make
> .next-handle also toss the remaining data in the $!decoder, then the
> OP code
> would work.
> 
> In the meantime, you can use `.get` instead:
> 
> my $limit := 3;
> my $lines = 1;
> with $*ARGFILES -> $af {
>     while ($_ := $af.get) !=:= Nil {
>         $lines == 1 and put "NEWFILE:";
>         put "$af.path():{$lines++} $_";
>         next unless $lines > $limit;
>         $af.next-handle and $lines = 1;
>     }
> }
> 
> I also noticed another deficiency: when trying to set .on-switch on
> $*ARGFILES,
> you always miss its very first call that's done by IO::CatHandle.new,
> since to give
>  you $*ARGFILES, .new has already been called.
> 
> Not sure what can be done about it, but I filed it as
> https://github.com/rakudo/rakudo/issues/1545 IO::CatHandle is not yet
> part of any
> language, so we have the ability to polish the rough edges.


Side note: it could be handy to be able to loop over IO::CatHandle's handles.
The OP code would just be:

    for $*ARGFILES.handles -> $fh {
        put "NEWFILE:";
        put "$fh.path():$(++$) $_" for $fh.lines: 3;
    }

Filed that as https://github.com/rakudo/rakudo/issues/1546

Reply via email to