I'm playing around with lines
which reads lines from the files you specify on the command line:
for lines() { put $_ }
If it can't read one of the filenames it throws X::AdHoc
(one day maybe it will have better exception types so we can grab the filename with a .path
method). Fine, so catch that:
try {
CATCH { default { put .^name } }
for lines() { put $_ }
}
So this catches the X::AdHoc
error but that's it. The try
block is done at that point. It can't .resume
and try the next file:
try {
CATCH { default { put .^name; .resume } } # Nope
for lines() { put $_ }
}
Back in Perl 5 land you get a warning about the bad filename and the program moves on to the next thing.
I could filter @*ARGS
first then reconstruct $*ARGFILES
if there are some arguments:
$*ARGFILES = IO::CatHandle.new:
@*ARGS.grep( { $^a.IO.e and $^a.IO.r } ) if +@*ARGS;
for lines() { put $_ }
That works although it silently ignores bad files. I could handle that but it's a bit tedious to handle the argument list myself, including -
for standard input as a filename and the default with no arguments:
my $code := { put $_ };
@*ARGS = '-' unless +@*ARGS;
for @*ARGS -> $arg {
given $arg {
when '-' { $code.($_) for $*IN.lines(); next }
when ! .IO.e { note "$_ does not exist"; next }
when ! .IO.r { note "$_ is not readable"; next }
default { $code.($_) for $arg.IO.lines() }
}
}
But that's a lot of work. Is there a simpler way to handle this?
To warn on bad open and move on, you could use something like this:
Simply mixing in a role that makes the IO::CatHandle.next-handle method re-try getting next handle. (you can also use
but
operator to mixin on a copy instead).The
X::AdHoc
is from.open
call; there's a somewhat moldy PR to make those exceptions typed, so once that's fixed,IO::CatHandle
would throw typed exceptions as well.Yeah, you can only resume from a
CATCH
block that caught it, but in this case it's caught inside.open
call and is made into aFailure
, which is then received byIO::CatHandle.next-handle
and its.exception
is re-.throw
n.However, even if it were resumable here, it'd simply resume into a path where exception was thrown, not re-try with another handle. It wouldn't help. (I looked into making it resumable, but that adds vagueness to
on-switch
and I'm not comfortable speccing that resumingException
s from certain places must be able to meaningfully continue—we currently don't offer such a guarantee for any place in core).Note that that special meaning is going away in 6.d language as far as
IO::Handle.open
(and by extensionIO::CatHandle.new
) goes. It might get special treatment inIO::ArgFiles
, but I've not seen that proposed.In Perl 6, it's implemented as a generalized
IO::CatHandle
type users can use for anything, not just file arguments, so warning and moving on by default feels too lax to me.IO::ArgFiles
could be special-cased to offer such behaviour. Personally, I'm against special casing stuff all over the place and I think that is the biggest flaw in Perl 5, but you could open an Issue proposing that and see if anyone backs it.