HiveBrain v1.2.0
Get Started
← Back to all entries
debugrustModerate

What Is the Rust Equivalent to a Try-Catch Statement?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
statementtheequivalentrustcatchwhattry

Problem

Is it possible to handle multiple different errors at once instead of individually in Rust without using additional functions? In short: what is the Rust equivalent to a Try-Catch statement?

A similar feature was suggested back in 2016, but I don't know what came of it.

For example, doing something like this:
try {
do_step_1()?;
do_step_2()?;
do_step_3()?;
// etc.
} catch {
alert_user("Failed to perform necessary steps");
}


Instead of:
match do_steps() {
Ok(_) => (),
_ => alert_user("Failed to perform necessary steps")
}

// Additional function:
fn do_steps() -> Result{
do_step_1()?;
do_step_2()?;
do_step_3()?;
// etc.
Ok(())
}


My program has a function which checks a variety of different places in the registry for different data values and returns some aggregate data. It would need to use many of these try-cache statements with try-catch inside of other try-catch inside of loops.

Solution

Results in Rust can be chained using and_then. So you can do this:

if let Err(e) = do_step_1().and_then(do_step_2).and_then(do_step_3) {
    println!("Failed to perform necessary steps");
}


or if you want a more compact syntax, you can do it with a macro:

macro_rules! attempt { // `try` is a reserved keyword
   (@recurse ($a:expr) { } catch ($e:ident) $b:block) => {
      if let Err ($e) = $a $b
   };
   (@recurse ($a:expr) { $e:expr; $($tail:tt)* } $($handler:tt)*) => {
      attempt!{@recurse ($a.and_then (|_| $e)) { $($tail)* } $($handler)*}
   };
   ({ $e:expr; $($tail:tt)* } $($handler:tt)*) => {
      attempt!{@recurse ($e) { $($tail)* } $($handler)* }
   };
}

attempt!{{
   do_step1();
   do_step2();
   do_step3();
} catch (e) {
   println!("Failed to perform necessary steps: {}", e);
}}


playground

Code Snippets

if let Err(e) = do_step_1().and_then(do_step_2).and_then(do_step_3) {
    println!("Failed to perform necessary steps");
}
macro_rules! attempt { // `try` is a reserved keyword
   (@recurse ($a:expr) { } catch ($e:ident) $b:block) => {
      if let Err ($e) = $a $b
   };
   (@recurse ($a:expr) { $e:expr; $($tail:tt)* } $($handler:tt)*) => {
      attempt!{@recurse ($a.and_then (|_| $e)) { $($tail)* } $($handler)*}
   };
   ({ $e:expr; $($tail:tt)* } $($handler:tt)*) => {
      attempt!{@recurse ($e) { $($tail)* } $($handler)* }
   };
}

attempt!{{
   do_step1();
   do_step2();
   do_step3();
} catch (e) {
   println!("Failed to perform necessary steps: {}", e);
}}

Context

Stack Overflow Q#55755552, score: 35

Revisions (0)

No revisions yet.