Io 我应该如何处理可以';不能逐行阅读()?

Io 我应该如何处理可以';不能逐行阅读()?,io,raku,Io,Raku,我正在玩行,它从您在命令行上指定的文件中读取行: for lines() { put $_ } 如果它不能读取它抛出的一个文件名X::AdHoc(也许有一天它会有更好的异常类型,这样我们就可以用.path方法获取文件名)。很好,所以请注意: try { CATCH { default { put .^name } } for lines() { put $_ } } 这捕获了X::AdHoc错误,但仅此而已。此时将完成try块。无法。请继续,然后尝试下一个文件: try { CATCH {

我正在玩
,它从您在命令行上指定的文件中读取行:

for lines() { put $_ }
如果它不能读取它抛出的一个文件名
X::AdHoc
(也许有一天它会有更好的异常类型,这样我们就可以用
.path
方法获取文件名)。很好,所以请注意:

try {
CATCH { default { put .^name } }
for lines() { put $_ }
}
这捕获了
X::AdHoc
错误,但仅此而已。此时将完成
try
块。无法
。请继续
,然后尝试下一个文件:

try {
CATCH { default { put .^name; .resume } }  # Nope
for lines() { put $_ }
}
回到Perl5Land,您会收到一条关于错误文件名的警告,程序将继续进行下一步

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

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

for lines() { put $_ }
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() }
        }
    }
尽管它会默默地忽略坏文件,但仍然有效。我可以处理这个问题,但自己处理参数列表有点繁琐,包括标准输入的
-
文件名和默认值(不带参数):

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

for lines() { put $_ }
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() }
        }
    }

但这需要做很多工作。是否有更简单的方法来处理此问题?

若要在错误打开时发出警告并继续,可以使用以下方法:

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

.say for lines
简单地说,这会使方法重新尝试获取下一个句柄。(您也可以使用混入副本)


如果它不能读取它抛出的一个文件名X::AdHoc

X::AdHoc
来自
.open
调用;有一个异常,所以一旦修复了它,
IO::CatHandle
也会抛出类型化异常

不行,继续

是的,您只能从捕获它的
CATCH
块恢复,但在这种情况下,它在
内被捕获。打开
调用,并进入
失败
,然后由
IO::CatHandle接收。下一个句柄
及其
.exception
是re-
.throw
n

然而,即使它在这里是可恢复的,它也只是恢复到引发异常的路径中,而不是使用另一个句柄重试。这没用。(我考虑过使其可恢复,但这给开关上的
增加了模糊性,我不愿意指定从某些位置恢复
异常必须能够有意义地继续,我们目前不为核心中的任何位置提供这样的保证)

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

请注意,这一特殊含义仅限于
IO::Handle.open
(扩展为
IO::CatHandle.new
)。它可能会在
IO::ArgFiles
中得到特殊处理,但我还没有看到这样的建议


回到Perl5Land,您会收到一条关于错误文件名的警告,程序将继续进行下一步

在Perl 6中,它被实现为一种通用的
IO::CatHandle
类型,用户可以用它来做任何事情,而不仅仅是文件参数,因此,在默认情况下,警告和继续前进对我来说太过宽松了


IO::ArgFiles
可以是提供这种行为的特殊情况。就我个人而言,我反对到处都是特殊外壳的东西,我认为这是Perl 5中最大的缺陷,但是你可以看看是否有人支持它。

我认为这里的错误实际上是一个错误。它不是带有a
.path
和b的类型化异常。它是不可恢复的。请为此创建GH issue/RT票证。@ElizabethMattijsen FWIW:查看规范,我们不保证
。恢复
核心抛出异常的能力;更不用说保证了。恢复将产生任何有意义的行为(例如使用下一个句柄重试)。在国际海事组织,我们不应该只是一时兴起就开始支持它,而应该看看是否可以作为一种通用模式支持整个核心。(FWIW使IO::CatHandle.next-handle直接抛出X::AdHoc,并在某个次要位置用“发生了错误(AdHoc)”,恢复后爆炸)我认为它应该作为序列的一部分给出,而不是抛出错误。如果错误出现在Seq中,那么它可以像调用
next
一样简单。@BradGilbert从
调用
Seq
?这将破坏(只读)IO::Handle和IO::CatHandle的可互换性,并且对其他方法没有帮助,例如
.read
.slurp
。在成功从“文件”中读取后,让它抛出“未找到文件”错误也会破坏可互换性。按照现在的工作方式,在用户代码中重新实现算法似乎比使用内置算法更容易;可能会导致新的Perl 6程序员编写了许多糟糕的重新实现。现在,您基本上必须知道如何实现它来解决它。有很多方法是不可互换的,比如试着写下来。我们的目标应该是有效地互换。(可能有比我提议的更好的办法,我接受)@BradGilbert我根本不明白你提议解决什么问题。该提案仅仅为用户创造了令人惊讶的行为,创建了隐藏(例如,
my@lines=lines
现在有未经证实的故障),增加了检查每一行错误的开销,并且对所有其他读取方法都没有解决任何问题。如果它以内联方式返回它们,您至少可以执行
.grep(&defined)
如果你不在乎失败。如果你真的在乎失败,但你希望能够继续;目前,你还不能完全做到这一点。