处理无效的文件句柄(也可能是其他无效对象)

jjm*_*elo 7 io exception-handling perl6

正如Tom Browder在本期中所指出的,如果命令行中提到的任何文件不存在,$*ARGFILES动态变量可能包含无效的文件句柄.

for $*ARGFILES.handles -> $fh {
    say $fh;
}
Run Code Online (Sandbox Code Playgroud)

将失败和X::AdHoc异常(这可能也应该改善):

Failed to open file /home/jmerelo/Code/perl6/my-perl6-examples/args/no-file: No such file or directory
Run Code Online (Sandbox Code Playgroud)

只要将无效的文件句柄用于任何操作,就会出现此问题.是否有办法在发生异常之前检查文件句柄是否有效?

Eli*_*sen 8

您可以检查,如果事情是Failure通过检查感实性或definedness 没有Failure投掷:

for $*ARGFILES.handles -> $fh {
    say $fh if $fh;  # check truthiness
    .say with $fh;   # check definedness + topicalization
}
Run Code Online (Sandbox Code Playgroud)

如果你仍然希望抛弃Exception那些Failure包围,那么你就可以.throw了.


rai*_*iph 3

TL;DR我以为 Liz 已经解决了,但似乎有一个错误,或者可能是呃。

一个错误?

看起来每当IO::CatHandle类的.handles方法到达一个句柄时,该句柄理应产生一个Failure异常(延迟任何异常抛出),但它会立即抛出一个异常(如果它只是被延迟或可能出现问题,则可能是一个可以工作的异常)。

这看起来要么是错误的,要么是非常错误的。

请参阅Zoffix 和 Brad Gilbert 之间的交流以及 Zoffix对问题How should I handle Perl 6 $*ARGFILES that can't be read bylines()? 的回答。

还:

目前潜在的解决方法是另一个错误?

在讨论“在 Zoffix++ 上实现打开失败的处理程序”IO::CatHandle"时,使用以下代码作为解决方案关闭了它:

.say for ($*ARGFILES but role {
    method next-handle {
        loop {try return self.IO::CatHandle::next-handle}
    }
})
Run Code Online (Sandbox Code Playgroud)

我看到 tbrowder 已重新打开此问题,作为此 SO 所涉及的相关问题的一部分:

如果这有效,那么它至少是$*ARGFILES文档中 var 的一个可用示例。

但是当我运行它6.d(并看到 a 的类似结果6.c)时,无论是否有有效输入,我都会得到:

say not yet implemented
Run Code Online (Sandbox Code Playgroud)

(如果我.put或其他什么也类似)。

这太疯狂了,表明一些勇敢的事情被搞砸了。

我在 rt 和 gh/rakudo 问题中搜索了“尚未实现”,但没有看到相关匹配项。

另一种解决方法?

Zofix 显然希望他们的代码成为永久解决方案,而不仅仅是一种解决方法。但不幸的是,它现在似乎根本不起作用。

到目前为止我想出的最好的:

try {$*ARGFILES} andthen say $_    # $_ is a defined ArgFiles instance
                 orelse  say $!;   # $! is an error encountered inside the `try`
Run Code Online (Sandbox Code Playgroud)

也许这是一个黑白分明的解决方案,要么全部有效,要么全部无效。(尽管我什至不相信是这样。)

医生有什么要说的$*ARGFILES

$*ARGFILES说它是一个实例

IO::ArgFiles它被记录为一个类

出于向后兼容性原因而存在并且不提供任何方法。

所有功能都继承自

IO::CatHandle其副标题为

使用多个 IO 句柄,就像它们是一个一样

并记录为一个类is

IO::Handle其副标题为

打开的文件或流

并被记录为不从任何其他类继承的类(因此默认继承自Any)或执行任何角色。

因此,$*ARGFILES它是(功能上完全相同)一个IO::CatHandle对象,它是一个对象(功能的超集)IO::Handle,具体来说:

该类IO::CatHandle提供了一种创建无缝收集来自多个来源的IO::Handle输入的方法。的所有方法都已实现,虽然尝试使用写入方法将(当前)引发异常,但 an可以在可以使用只读方法的任何地方使用。IO::HandleIO::PipeIO::HandleIO::CatHandleIO::Handle

探索代码IO::CatHandle

(稍后填写?)