Remix.run Logo
koakuma-chan 3 days ago

I have one better: the try block pattern.

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

Sytten 3 days ago | parent | next [-]

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

mbrubeck 2 days ago | parent | next [-]

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

mmastrac 3 days ago | parent | prev | next [-]

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

koakuma-chan 3 days ago | parent | prev | next [-]

#![feature(try_blocks)]

You only live once.

dwattttt 2 days ago | parent [-]

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

JoshTriplett 2 days ago | parent [-]

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

stouset 2 days ago | parent | prev [-]

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

masklinn 2 days ago | parent | next [-]

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

lunar_mycroft 2 days ago | parent | prev [-]

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.

loeg 2 days ago | parent | prev | next [-]

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>()?)
    })();
rendaw 2 days ago | parent | next [-]

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.

ahartmetz 2 days ago | parent [-]

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.

dzaima 2 days ago | parent [-]

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.

skribanto 2 days ago | parent [-]

Why couldnt you flatten it?

dzaima 13 hours ago | parent [-]

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.

schneems 2 days ago | parent | prev | next [-]

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.

pflanze 2 days ago | parent [-]

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...

saghm 2 days ago | parent | prev [-]

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

ahartmetz 2 days ago | parent | next [-]

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.

nicoburns 2 days ago | parent [-]

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

saghm 2 days ago | parent [-]

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

loeg 2 days ago | parent | prev [-]

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

tayo42 3 days ago | parent | prev | next [-]

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

bobbylarrybobby 2 days ago | parent | next [-]

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.

mwcz 2 days ago | parent | prev | next [-]

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.

jeroenhd 2 days ago | parent | prev | next [-]

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...

koakuma-chan 3 days ago | parent | prev [-]

One reason is that would be a breaking change.

valcron1000 2 days ago | parent | prev | next [-]

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

oniony 3 days ago | parent | prev | next [-]

Now that is pretty cool.

satvikpendem 2 days ago | parent | prev [-]

Ah yes, do-notation.