Too many nested match?


#1

Hi folks,

I am a little un-easy on the level of depth of nested match.

I have code that looks like this in several place of my code base.

match f() {
    Err(e) => e.reply(),
    Ok(x) => match g(x) {
        Err(e) => e.reply(),
        Ok(y) => match h(y) {
            Err(e) => e.reply(),
            Ok(z) => match t(z) {
                Err(e) => e.reply()
                Ok(g) => j(g)
            }
        }
    }
}

The problem with this pattern is that is extremely difficult to modify code in the middle, especially add other matches since it is difficult to understand where close the brackets.
Sure it is a kind of trivial problem but I have lost quite some time in this issue.

Clearly re-write the code and keep the functions shorter would alleviate this problem but I am wondering if I am missing something fundamental.

I am quite more con


#2

f().and_then(g).and_then(h).and_then(t).and_then(j).unwrap_or_else(|e| e.reply())

See:

https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_else
and
https://doc.rust-lang.org/std/result/enum.Result.html#method.and_then


#3

I would suggest going through the “Error Handling” section of the Rust book. It does quite a good job of explaining how to deal with this kind of error composition issues.

To whet your appetite, your code could for example be rewritten as:

// Linear version
let try_linear = || {
    let x = f()?;
    let y = g(x)?;
    let z = h(y)?;
    t(z)
};
match try_linear() {
    Err(e) => e.reply(),
    Ok(g) => j(g),
}

// Nested version
let try_nested = || { t(h(g(f()?)?)?) };
match try_nested() {
    Err(e) => e.reply(),
    Ok(g) => j(g),
}

(If you’re confused by the ? syntax, it’s basically some syntaxic sugar for the try! macro discussed by the Rust book)