# Let … else if … else

**URL:** <https://internals.rust-lang.org/t/let-else-if-else/20690>\
**Category:** language design\
**Created:** [April 21, 2024, 9:32am UTC](https://internals.rust-lang.org/t/let-else-if-else/20690 "2024-04-21T09:32:31Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dwarsloeper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dwarsloeper/32/11073_2.png) [@Dwarsloeper](https://internals.rust-lang.org/u/Dwarsloeper)\
**Post date:** [April 21, 2024, 9:32am UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/1 "2024-04-21T09:32:31Z")

</div>

I just had a use case for

```rust
let Some(x) = y
else if its_ok {
    break
} else {
    return Err("It's not ok!")
};

```

But Rust deviated from its rule of `else` must be followed by a block or `if`. DuckDuckGo doesn't find anything for "let else if". So, was there no discussion about this obvious feature?

Of course it could be worked around with ugly nesting, but then so could any `else if`. Though useful for avoiding nesting, `let else` is already an odd feature. It shouldn't be odder than necessary by introducing an exception for what can follow `else`!

N.b. this is a more natural extension than [Pre-Pre-RFC: `let else match` statement](https://internals.rust-lang.org/t/pre-pre-rfc-let-else-match-statement/17691)

---

<div class="post-metadata">

**Author:** ![parasyte](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/parasyte/32/8925_2.png) [@parasyte](https://internals.rust-lang.org/u/parasyte)\
**Post date:** [April 21, 2024, 10:53am UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/2 "2024-04-21T10:53:36Z")

</div>

This reads better to me, but it's clearly a subjective quality:

```rust
let x = match y {
    Some(x) => x,
    None if its_ok => break,
    None => return Err("It's not ok!"),
};

```

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [April 21, 2024, 9:45pm UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/3 "2024-04-21T21:45:47Z")

</div>

A reasonable rationale for why let-else doesn't have let-else-if is a combination of:

- Because the `let` introduces a binding into the containing scope, the `else` clause is required to diverge. Due to this, it's not at the same "level" of control flow like the various conditions of an if-else-if are.
- Avoiding ambiguity _for the human_ relies on `} else` always being the `else` of an if-else, and never a let-else. This would break that property.

My baseline response is that the this could make sense, but is ultimately driven by just a desire to remove syntactic nesting instead of allowing the code to better correspond to the logical control flow structure.

let-else-match isn't exclusively about reducing nesting; the claimed value-add is that the `match` retains access to the scrutinee on failed a pattern match whereas let-else drops it.

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [April 22, 2024, 12:08pm UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/4 "2024-04-22T12:08:09Z")

</div>

> [@CAD97](#):
>
> let-else-match isn't exclusively about reducing nesting; the claimed value-add is that the `match` retains access to the scrutinee on failed a pattern match whereas let-else drops it.

I don't get it, is this explained in any document? Is this a literal early drop?

---

<div class="post-metadata">

**Author:** ![FZs](https://avatars.discourse-cdn.com/v4/letter/f/85f322/32.png) [@FZs](https://internals.rust-lang.org/u/FZs)\
**Post date:** [April 22, 2024, 7:52pm UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/5 "2024-04-22T19:52:24Z")

</div>

```rust
let Ok(v) = get_result() else{
    //no access to Err here
    return;
}

```

vs

```rust
//hypothetical syntax
let Ok(v) = get_result() else match{
    Err(e) => return e.message
}

```

---

<div class="post-metadata">

**Author:** ![idanarye](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/idanarye/32/3346_2.png) [@idanarye](https://internals.rust-lang.org/u/idanarye)\
**Post date:** [April 25, 2024, 2:12pm UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/6 "2024-04-25T14:12:16Z")

</div>

I'd be more interested in `let` ... `else let` and `let` ... `else let` ... `else`:

```rust
let Some(x) = foo() else
let Ok(x) = bar() else
let x = baz();

```

`foo()` and `bar()`, of course, will need to return types with the same [output](https://doc.rust-lang.org/std/ops/trait.Try.html#associatedtype.Output) which would also be the return type of `baz()`, because they'd be bound to the same `x`.

Not sure about how this should be formatted though...

---

<div class="post-metadata">

**Author:** ![geniusisme](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/geniusisme/32/1172_2.png) [@geniusisme](https://internals.rust-lang.org/u/geniusisme)\
**Post date:** [April 26, 2024, 2:27pm UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/7 "2024-04-26T14:27:22Z")

</div>

You can do that with rust monadic API:

> **[Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f019816d67a856f2a9c17eccb288fdd8)**
>
> A browser interface to the Rust compiler to experiment with the language

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [July 25, 2024, 2:28pm UTC](https://internals.rust-lang.org/t/let-else-if-else/20690/8 "2024-07-25T14:28:22Z")

</div>

Closed on July 25, 2024, 2:28pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
