我应该如何处理行()无法读取的Perl 6 $*ARGFILES?

bri*_*foy 10 io perl6 raku

我正在玩弄lines你从命令行中指定的文件中读取行:

for lines() { put $_ }
Run Code Online (Sandbox Code Playgroud)

如果它无法读取它抛出的X::AdHoc其中一个文件名(有一天它可能会有更好的异常类型,因此我们可以使用.path方法获取文件名).很好,所以赶上:

try {
CATCH { default { put .^name } }
for lines() { put $_ }
}
Run Code Online (Sandbox Code Playgroud)

所以这就抓住了X::AdHoc错误,但就是这样.该try块在那时完成.它不能.resume并尝试下一个文件:

try {
CATCH { default { put .^name; .resume } }  # Nope
for lines() { put $_ }
}
Run Code Online (Sandbox Code Playgroud)

回到Perl 5的土地,你得到一个关于坏文件名的警告,程序继续下一步.

如果有一些参数,我可以@*ARGS先过滤然后重建$*ARGFILES:

$*ARGFILES = IO::CatHandle.new:  
    @*ARGS.grep( { $^a.IO.e and $^a.IO.r } ) if +@*ARGS;

for lines() { put $_ }
Run Code Online (Sandbox Code Playgroud)

尽管它默默地忽略了坏文件,但仍然有效.我可以处理这个,但是自己处理参数列表有点乏味,包括-标准输入作为文件名和默认情况下没有参数:

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() }
        }
    }
Run Code Online (Sandbox Code Playgroud)

但这是很多工作.有没有更简单的方法来处理这个?

小智 5

要警告糟糕的打开并继续前进,您可以使用以下内容:

$*ARGFILES does role { method next-handle { loop {
    try return self.IO::CatHandle::next-handle;
    warn "WARNING: $!.message"
}}}

.say for lines
Run Code Online (Sandbox Code Playgroud)

只需混合一个角色,使IO :: CatHandle.next-handle方法重新尝试获取下一个句柄.(您也可以使用but运算符混合复制).


如果它无法读取其中一个文件名,则会抛出X :: AdHoc

X::AdHoc是从.open呼叫; 有一些发霉的PR可以使这些异常类型化,所以一旦修复了,IO::CatHandle就会抛出类型异常.

它不能.resume

是的,你只能从CATCH捕获它的块中恢复,但是在这种情况下它被捕获到内部.open并被制成a Failure,然后被接收IO::CatHandle.next-handle并且它.exception被重新接收.throw.

然而,即使它在这里可以恢复,它也只是简单地恢复到抛出异常的路径,而不是用另一个句柄重新尝试.这没有用.(我考虑使其可恢复,但这增加了模糊性,on-switch并且我不习惯指出Exception从某些地方恢复s必须能够有意义地继续 - 我们目前不为核心中的任何地方提供这样的保证).

包括-标准输入作为文件名

请注意,特殊含义在6.D语言消失尽可能IO::Handle.open(通过扩展IO::CatHandle.new)进入.它可能会得到特殊处理IO::ArgFiles,但我没有看到提出的建议.


回到Perl 5的土地,你得到一个关于坏文件名的警告,程序继续下一步.

在Perl 6中,它被实现为IO::CatHandle用户可以用于任何事物的通用类型,而不仅仅是文件参数,因此默认情况下警告和移动对我来说太麻烦了.

IO::ArgFiles可以特别提供这种行为.就我个人而言,我反对在整个地方使用特殊的外壳,我认为这是Perl 5中最大的缺陷,但是你可以打开一个提出这个问题的问题,看看是否有人支持它.