在 try 块中作为最后一条语句运行时可能出现的错误

问题描述 投票:0回答:1

我不知道这是否是一个错误,或者我只是不明白发生了什么。如果我有一个

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
块可能出现在引发异常的行范围内的任何位置。如果我错了请纠正我。

exception raku rakudo
1个回答
0
投票

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!
© www.soinside.com 2019 - 2024. All rights reserved.