Reputation: 1189
I don't know if this is a bug, or I just don't understand what's happening. If I have a run
statement as the last statement in a try
block, any error in the run
statement is not caught. If it is not the last statement in the block, the exception is caught. Here's what I get when run
is the last statement:
try {
CATCH {
default {
say 'CAUGHT!';
}
}
run 'lss', '-al';
}
Output:
$ 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
Here's what I get if it isn't the last statement:
try {
CATCH {
default {
say 'CAUGHT!';
}
}
run 'lss', '-al';
say 'foo';
}
Output:
$ raku try-run-bug-workaround.raku
CAUGHT!
This has been tested on:
$ raku -v
Welcome to Rakudo™ v2024.09.
Implementing the Raku® Programming Language v6.d.
Built on MoarVM version 2024.09.
via rakubrew.
Edit
Based on a comment below, I did try moving the CATCH
block to the bottom in the first example, and it did fix the problem. It still seems like a bug to me because I thought that CATCH
blocks could appear anywhere within the scope of the line that throws the exception. Please correct me if I'm wrong.
Upvotes: 6
Views: 129
Reputation: 9600
run
returns a Proc
object, and Proc
s behave differently in sink context versus expression context. Specifically, in expression context, a Proc
isn't run immediately (more or less like a lazy computation); instead, it's run when you call methods that require it to be run, such as .spawn
, .out.slurp
, or .exitcode
.
Another method that runs a Proc
is sink
(which runs the command and throws an error if it failed). All that happens when a Proc
is in sink context is that the .sink
method gets called automatically.
With that background, we should be able to see why run
behaves differently in your two code examples. At first, it might look like they're both in sink context since nether value is used. But remember: Raku blocks implicitly return their final expression – so when the run
command is that final expression, it gets returned and thus is not in sink context. (The block
that contains run
is in sink context, but that doesn't "flow through" to the run
).
But we can tell Raku what context we want. Specifically, we can use sink
statement prefix:
try {
CATCH {
default {
say 'CAUGHT!';
}
}
sink run 'lss', '-al';
}
And once we're explicit about the context we want, we get the expected result:
CAUGHT!
Upvotes: 0