I've searched to see if my idea was already suggested, and found [IDEA] `.catch` which was closed on 2023. Let's continue the discussion from there.
The objection on the first comment of that post is that the Try
trait cannot provide the error type E
- only the Residual
, which is Result<!, E>
.
But... is this really a problem? With the never type and with irrefutable patterns, all this means that we need to destruct the Residual
in the .catch
's pattern, which means the example in the original post would look like this:
let value = this_may_fail().catch Err(err) {
if err.recoverable() { fallback_value }
else { return }
}
I've managed to get the semantics to work with a macro:
3 Likes
What's the benefit of using this over a regular match
, which could handle your example like:
let value = match this_may_fail() {
Ok(value) => value,
Err(e) if e.recoverable() => fallback_value,
Err(_) => return,
};
Is the benefit just that you save the Ok(value) => value
line? Or is there something this handles that a normal match
(or the postfix match idea people have been floating) can't handle?
1 Like
As with anything that gets lowered to a match
, there is nothing it can do that can't be done with a regular match
. The main advantage is convenience, and in this case the main advantage is that you can chain these multiple catch
s in the same expression:
foo().catch Err(_) { default_foo_value }
.bar().catch Err(_) { continue }
.baz().catch None { return Err(Error::BazIsNone) };
(the e.recoverable()
check is mainly a copy-paste from the original post)
Also - this combines nicely with a try block:
try {
do_something()?;
do_something_else()?;
}.catch Err(e) {
tracing::error!("Failed! {e}");
}
3 Likes
What's the benefit of using if
, if let
, if..else
, or let..else
over a regular match
, which could handle any of these cases?
If we get postfix macros at some point, the same convenience could be achieved with a macro version of unwrap_or_else
:
let value = this_may_fail().unwrap_or!(e => {
if e.recoverable() {
fallback_value
} else {
return;
}
});