我不知道这是否是一个错误,或者我只是不明白发生了什么。如果我有一个
run
语句作为 try
块中的最后一个语句,则不会捕获 run
语句中的任何错误。如果它不是块中的最后一条语句,则捕获异常。这是当 run
是最后一条语句时我得到的结果:
try {
CATCH {
default {
say 'CAUGHT!';
}
}
run 'lss', '-al';
}
输出:
$ raku try-run-bug.raku
The spawned command 'lss' exited unsuccessfully (exit code: -1, signal: 254)
(OS error = Failed to spawn process lss: no such file or directory (error code -2))
in block <unit> at try-run-bug.raku line 1
如果这不是最后一个陈述,这就是我得到的:
try {
CATCH {
default {
say 'CAUGHT!';
}
}
run 'lss', '-al';
say 'foo';
}
输出:
$ raku try-run-bug-workaround.raku
CAUGHT!
这已经过测试:
$ raku -v
Welcome to Rakudo™ v2024.09.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2024.09.
通过 rakubrew。
编辑
根据下面的评论,我确实尝试将第一个示例中的
CATCH
块移动到底部,它确实解决了问题。对我来说,这仍然像是一个错误,因为我认为 CATCH
块可能出现在引发异常的行范围内的任何位置。如果我错了请纠正我。
run
返回一个 Proc
对象,并且 Proc
在 sink 上下文 与表达式上下文中的行为不同。具体来说,在表达式上下文中, Proc
不会立即运行(或多或少像惰性计算);相反,当您调用需要运行它的方法时,它就会运行,例如 .spawn
、.out.slurp
或 .exitcode
。
运行
Proc
的另一种方法是 sink
(它运行命令并在失败时抛出错误)。当 Proc
处于接收器上下文中时,会自动调用 .sink
方法。
有了这个背景,我们应该能够明白为什么
run
在两个代码示例中表现不同。起初,由于使用了下一个值,因此它们可能看起来都在接收器上下文中。但请记住:Raku 块隐式返回它们的最终表达式 - 因此,当 run
命令是最终表达式时,它会被返回,因此在接收器上下文中不是。 (包含 block
的 run
位于接收器上下文中,但不会“流经”到 run
)。
但是我们可以告诉 Raku 我们想要什么上下文。具体来说,我们可以使用
sink
语句前缀:
try {
CATCH {
default {
say 'CAUGHT!';
}
}
sink run 'lss', '-al';
}
一旦我们明确了我们想要的上下文,我们就得到了预期的结果:
CAUGHT!