Why `yeet` in `try` blocks if `break` is good enough?

Hello, as far as I can remember, yeet is a proposed keyword to return from try block with error. I'm not sure why is it needed if something like that seems like a good potential syntax:

'block: try {
    if foo {
        break 'block Err(err);
    }
}

What are your thoughts about it?

2 Likes

Actually yeet is exactly used as placeholder to prevent bikeshedding.

9 Likes

We have dedicated constructs for common things even if they could be expressed another way. (For instance, we have if let even though you can always write match.) This is especially true when the dedicated construct makes the intent clearer at a glance.

A dedicated construct to bail with an error, whether from a try block or a whole function, would be much more convenient and simple, avoid making people spend extra time figuring out what it's doing, and add uniformity/orthogonality across usages.

8 Likes

One way of looking at things is that all you really need are Iota and Jot - Wikipedia. So just about everything in syntax is more of a taste question than anything truly unambiguous.

Certainly we could write

if foo {
    return Err(e);
}

as

match foo {
    true => break 'fn Err { 0: e },
    false => {}
}

because we don't need if, and from a Boolean Blindness | Existential Type perspective that can even be considered "better" in some ways.

5 Likes

12 posts were merged into an existing topic: Some yeet bikeshedding, just for fun

A difference is that you've written break 'try Err(err) (an "outer" break) but with yeet it's do yeet err (an "inner" break that does try-wrapping for you).

4 Likes

Error only works well with Result; not all early returns are errors.

1 Like

Not always.

#![feature(try_blocks)]
#![feature(yeet_expr)]
fn ex(b: bool) {
    let _: Option<i32> = try {
        if b {
            do yeet;
        }
        0
    };
}
1 Like

Um, so yeet works with ControlFlow (and apparently Poll of option and result of I read the docs correctly) ? That might be a bit confusing and open to code obfuscation.

Also why no Poll of ControlFlow?

Actually, no, at least not on the current nightly. do yeet requires the trying context to implement FromResidual<Yeet<T>>, where T is the type being yeet. The only two implementations currently provided are Yeet<()> for Option<_> and Yeet<E> for Result<_, impl From<E>>.

I personally think this was an API design mistake[1], but the way it works is Result<T, E>, Poll<Result<T, E>>, and Poll<Option<Result<T, E>>> share the same "residual" class, and ? on any of those types works in a try context with any of those types to yeet the Result::Err (if present), outputting T where the Result was.


  1. IMO, Poll should've used Poll<Infallible> as the residual with ? yeeting Poll::Pending, and using FromResidual to allow using ? on Result within a poll function, without allowing ? on Poll outside of poll functions. Then we'd no longer need to write ready!(inner.poll(cx)?); it'd just be inner.poll(cx)??. ↩ī¸Ž

3 Likes