Skip Menu |
Report information
Id: 132885
Status: open
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: comdog <brian.d.foy [at] gmail.com>
Cc:
AdminCc:

Severity: (no value)
Tag: (no value)
Platform: (no value)
Patch Status: (no value)
VM: (no value)



To: rakudobug [...] perl.org
Subject: .next-handle seems to change handles but doesn't
Date: Mon, 19 Feb 2018 19:14:30 -0500
From: brian d foy <brian.d.foy [...] gmail.com>
Download (untitled) / with headers
text/plain 1.5k
#!/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.
To: perl6-bugs-followup [...] perl.org
Subject: Re: [perl #132885] AutoReply: .next-handle seems to change handles but doesn't
Date: Mon, 19 Feb 2018 19:55:45 -0500
From: brian d foy <brian.d.foy [...] gmail.com>
Download (untitled) / with headers
text/plain 535b
I can fix this by closing the old file handle and checking the new one, but that seems like way to much work at the user level. quietly { my $limit = 5; for lines() { state $lines = 1; FIRST { $*ARGFILES.on-switch = { put "NEW FILE"; $lines = 1 } } if $lines > $limit { $*ARGFILES.next-handle.close; last unless $*ARGFILES.opened; next; } put "{$*ARGFILES.path}:{$lines++} $_"; } }
RT-Send-CC: perl6-compiler [...] perl.org
On Mon, 19 Feb 2018 16:15:37 -0800, comdog wrote: Show quoted text
> #!/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.
RT-Send-CC: perl6-compiler [...] perl.org
Download (untitled) / with headers
text/plain 3.4k
On Mon, 19 Feb 2018 19:48:30 -0800, cpan@zoffix.com wrote: Show quoted text
> 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


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org