Dealing with invalid filehandles (and maybe other invalid objects too)
You can check if something is a Failure
by checking for truthiness or definedness without the Failure
throwing:
for $*ARGFILES.handles -> $fh {
say $fh if $fh; # check truthiness
.say with $fh; # check definedness + topicalization
}
If you still want to throw the Exception
that the Failure
encompasses, then you can just .throw
it.
TL;DR I thought Liz had it nailed but it seems like there's a bug or perhaps Ugh.
A bug?
It looks like whenever the IO::CatHandle
class's .handles
method reaches a handle that ought by rights produce a Failure
(delaying any exception throw) it instead immediately throws an exception (perhaps the very one that would work if it were just delayed or perhaps something broken).
This seems either wrong or very wrong.
Ugh
See the exchange between Zoffix and Brad Gilbert and Zoffix's answer to the question How should I handle Perl 6 $*ARGFILES that can't be read by lines()?
Also:
https://github.com/rakudo/rakudo/issues/1313
https://github.com/rakudo/rakudo/search?q=argfiles&type=Issues
https://github.com/rakudo/rakudo/search?q=cathandle&type=Issues
A potential workaround is currently another bug?
In discussing "Implement handler for failed open on IO::CatHandle"
Zoffix++ closed it with this code as a solution:
.say for ($*ARGFILES but role {
method next-handle {
loop {try return self.IO::CatHandle::next-handle}
}
})
I see that tbrowder has reopened this issue as part of the related issue this SO is about saying:
If this works, it would at least be a usable example for the
$*ARGFILES
var in the docs.
But when I run it in 6.d
(and see similar results for a 6.c
), with or without valid input, I get:
say not yet implemented
(similar if I .put
or whatever).
This is nuts and suggests something gutsy is getting messed up.
I've searched rt and gh/rakudo issues for "not yet implemented" and see no relevant matches.
Another workaround?
Zoffix clearly intended their code as a permanent solution, not merely a workaround. But it unfortunately doesn't seem to work at all for now.
The best I've come up with so far:
try {$*ARGFILES} andthen say $_ # $_ is a defined ArgFiles instance
orelse say $!; # $! is an error encountered inside the `try`
Perhaps this works as a black-and-white it either all works or none of it does solution. (Though I'm not convinced it's even that.)
What the doc has to say about $*ARGFILES
$*ARGFILES
says it is an instance of
IO::ArgFiles
which is doc'd as a class which
exists for backwards compatibility reasons and provides no methods.
And
All the functionality is inherited from
IO::CatHandle
which is subtitled as
Use multiple IO handles as if they were one
and doc'd as a class that is
IO::Handle
which is subtitled as
Opened file or stream
and doc'd as a class that doesn't inherit from any other class (so defaults to inheriting from Any
) or do any role.
So, $*ARGFILES
is (exactly functionally the same as) a IO::CatHandle
object which is (a superset of the functionality of) an IO::Handle
object, specifically:
The
IO::CatHandle
class provides a means to create anIO::Handle
that seamlessly gathers input from multipleIO::Handle
andIO::Pipe
sources. All ofIO::Handle
's methods are implemented, and while attempt to use write methods will (currently) throw an exception, anIO::CatHandle
is usable anywhere a read-onlyIO::Handle
can be used.
Exploring the code for IO::CatHandle
(To be filled in later?)