处理无效文件句柄(可能还有其他无效对象)

Dealing with invalid filehandles (and maybe other invalid objects too)

正如 Tom Browder 在 this issue, the $*ARGFILES dynamic variable 中指出的那样,如果命令行中提到的任何文件不存在,则可能包含无效的文件句柄。

for $*ARGFILES.handles -> $fh {
    say $fh;
}

将失败并出现 X::AdHoc 异常(这可能也应该改进):

Failed to open file /home/jmerelo/Code/perl6/my-perl6-examples/args/no-file: No such file or directory

一旦将无效的文件句柄用于任何用途,就会出现此问题。有没有办法在引发异常之前检查文件句柄是否有效?

您可以通过检查真实性或定义性来检查某物是否是 Failure 而无需 Failure 抛出:

for $*ARGFILES.handles -> $fh {
    say $fh if $fh;  # check truthiness
    .say with $fh;   # check definedness + topicalization
}

如果您仍然想抛出 Failure 包含的 Exception,那么您可以 .throw 它。

TL;DR 我以为 Liz 已经搞定了,但似乎有一个错误或者呃。

错误?

看起来每当 IO::CatHandle class's .handles method 到达一个句柄,根据权利应该产生一个 Failure(延迟任何异常抛出),它会立即抛出一个异常(也许是如果它只是延迟了或者可能有问题。

这似乎是错误的或非常错误的。

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()?

还有:

目前可能的解决方法是另一个错误?

在讨论中 "Implement handler for failed open on IO::CatHandle" Zoffix++ 将其关闭并使用此代码作为解决方案:

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

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

If this works, it would at least be a usable example for the $*ARGFILES var in the docs.

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

say not yet implemented

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

这太疯狂了,暗示一些大胆的事情被搞砸了。

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

另一个解决方法?

Zoffix 明确打算将他们的代码作为永久解决方案,而不仅仅是解决方法。但不幸的是,它现在似乎根本不起作用。

迄今为止我想到的最好的:

try {$*ARGFILES} andthen say $_    # $_ is a defined ArgFiles instance
                 orelse  say $!;   # $! is an error encountered inside the `try`

也许这可以作为一个 black-and-white 它要么全部有效,要么 none 解决。 (虽然我什至不相信它是那样。)

医生对 $*ARGFILES

的评价

$*ARGFILES 表示它是

的实例

IO::ArgFiles 被记录为 class 其中

exists for backwards compatibility reasons and provides no methods.

All the functionality is inherited from

IO::CatHandle 副标题为

Use multiple IO handles as if they were one

并记录为 class 即 is

IO::Handle 副标题为

Opened file or stream

并记录为 class,它不继承自任何其他 class(因此默认继承自 Any)或扮演任何角色。

所以,$*ARGFILES 是(在功能上完全相同)一个 IO::CatHandle object 是一个 IO::Handle [=137](功能的超集) =],特别是:

The IO::CatHandle class provides a means to create an IO::Handle that seamlessly gathers input from multiple IO::Handle and IO::Pipe sources. All of IO::Handle's methods are implemented, and while attempt to use write methods will (currently) throw an exception, an IO::CatHandle is usable anywhere a read-only IO::Handle can be used.

探索the code for IO::CatHandle

(待补?)