Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.next-handle seems to change handles but doesn't #6676

Open
p6rt opened this issue Feb 20, 2018 · 5 comments
Open

.next-handle seems to change handles but doesn't #6676

p6rt opened this issue Feb 20, 2018 · 5 comments

Comments

@p6rt
Copy link

p6rt commented Feb 20, 2018

Migrated from rt.perl.org#132885 (status was 'open')

Searchable as RT132885$

@p6rt
Copy link
Author

p6rt commented Feb 20, 2018

From @briandfoy

#!/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.

@p6rt
Copy link
Author

p6rt commented Feb 20, 2018

From @briandfoy

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++} $_";
  }
  }

@p6rt
Copy link
Author

p6rt commented Feb 20, 2018

From @zoffixznet

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\}&#8203;:\{$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&#8203;:1 First
test\.txt&#8203;:2 Second
test\.txt&#8203;:3 Third
test\.txt&#8203;:4 Fourth
test\.txt&#8203;: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
rakudo/rakudo#1545 IO​::CatHandle is not yet part of any
language, so we have the ability to polish the rough edges.

@p6rt
Copy link
Author

p6rt commented Feb 20, 2018

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Feb 20, 2018

From @zoffixznet

On Mon, 19 Feb 2018 19​:48​:30 -0800, cpan@​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
rakudo/rakudo#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 rakudo/rakudo#1546

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant