I have one better: the try block pattern.

https://doc.rust-lang.org/beta/unstable-book/language-featur...

I want that stabilized so bad but it's not been really moving forward.

There's some active work recently on fixing blocking issues, e.g.:

https://github.com/rust-lang/rust/pull/148725

https://github.com/rust-lang/rust/pull/149489

I was not a fan when I first saw it but I'm becoming desperate to have it the more Rust I write.

#![feature(try_blocks)]

You only live once.

I've tried it recently, from memory error inference wasn't that great through it.

That's exactly what's currently being fixed before stabilizing it.

Out of curiosity why can’t a block just do this natively?

Because it would massively alter langage semantics? It converts returns from the nearest function into returns from the nearest (try) block.

Because then you couldn't use ? to propagate errors if they occurred inside any loops or branches within the function, which would be a significant limitation.

Can this just be done as a lambda that is immediately evaluated? It's just much more verbose.

    let x = (|| -> Result<i32, std::num::ParseIntError> {
         Ok("1".parse::<i32>()?
          + "2".parse::<i32>()?
          + "3".parse::<i32>()?)
    })();

That prevents other control flow mechanisms (return, break) from operating past the function boundary. In general, I avoid single-callsite functions as much as possible (including the iterator api) for this reason.

It sounds like you're fighting the language - Rust is sort of FP-light and you're encouraged to return a null/error value from the intermediate calculation instead of doing an early return from the outer scope. It's a nice and easy to follow way to structure the code IME. Yes, it's more verbose when an early return would have been just right - so be it.

For the case where `try` is useful over the functional form (i.e. parent's situation of having a desired Result, plus some unrelated early-returning), that ends up with nested `Result`s though, i.e. spamming an `Ok(Ok(x))` on all the non-erroring cases, which gets ugly fast.

Why couldnt you flatten it?

You have three different value cases (main value, main Err case for `?` to consume, and whatever early-return case). And the `?` operator fully taking up the Err result case means your main-result+early-return values strictly must both be wrapped in an Ok.

Wouldn't that also move any referenced variables too? Unlike the block example that would make this code not identical to what it's replacing.

No, unless you ask for it via the `move` keyword in front of the closure.

This works fine: https://play.rust-lang.org/?version=stable&mode=debug&editio...

My instinct is this would get hairy much faster if you want to actually close over variables compared to using a block.

Not sure if that is relevant to your point, but: For better and for worse, closing over any outer scope variables is syntactically free in Rust lambdas. You just access them.

It's syntactically free, but it can cause borrow-checker errors thst cause your code to outright fail to compile.

Yes, exactly. My concerns were semantic, not syntactic.

If the verbose return type syntax can't be elided, I think it's more or less dead as a pattern.

Why does this need special syntax? Couldn't blocks do this if the expression returns a result in the end?

Try blocks let you encapsulate the early-return behavior of Try-returning operations so that they don't leak through to the surrounding function. This lets you use the ? operator 1. when the Try type doesn't match that of the function this is taking place in 2. when you want to use ? to short circuit, but don't want to return from the enclosing function. For instance, in a function returning Result<T,E>, you could have a try block where you do a bunch of operations with Option and make use of the ? operator, or have ? produce an Err without returning from the enclosing function. Without try blocks, you pretty much need to define a one-off closure or function so that you can isolate the use of ? within its body.

The best part of try blocks is the ability to use the ? operator within them. Any block can return a result, but only function blocks (and try blocks) can propagate an Err with the ? operator.

Not without being able to use the ? operator.

The closest thing I can think of that will let you return a result from within a separate scope using a set of foo()? calls would be a lambda function that's called immediately, but that has its own problems when it comes to moving and it probably doesn't compile to very fast code either. Something like https://play.rust-lang.org/?version=stable&mode=debug&editio...

One reason is that would be a breaking change.

One of the first things I tried in Rust a couple of years ago coming from Haskell. Unfortunately it's still not stabilized :(

Now that is pretty cool.

Ah yes, do-notation.