Best practice for many error checks (there is no `unless let` in Rust)

I recently learned Result and match and if let in Rust. It’s clean way compared to try ... catch approach but for many error checks and without unless in syntax will give, for example, the following deep nesting.

fn main() {
    if let Ok(a1) = f0(a0) {
        if let Ok(a2) = f1(a1) {
            if let Ok(a3) = f2(a2) {
                f3(a3)
            } else {
                g3()
            }
        } else {
            g2()
        }
    } else {
        g1()
    }
}

If there is unless, it might will be

fn h(a0: A0): B {
    unless let Ok(a1) = f0(a0) {
        return g1();
    }
    unless let Ok(a2) = f1(a1) {
        return g2();
    }
    unless let Ok(a3) = f2(a2) {
        return g3();
    }
    f3(a3)
}

What is the Rust-way to prevent such deep nesting, or should I not avoid them?

This is spelled let … else { … }; in Rust:

fn h(a0: A0): B {
    let Ok(a1) = f0(a0) else {
        return g1();
    };
    let Ok(a2) = f1(a1) else {
        return g2();
    };
    let Ok(a3) = f2(a2) else {
        return g3();
    };
    f3(a3)
}
10 Likes