# Replace \`if let\` syntax

**URL:** <https://internals.rust-lang.org/t/replace-if-let-syntax/17373>\
**Category:** language design\
**Created:** [September 11, 2022, 8:45pm UTC](https://internals.rust-lang.org/t/replace-if-let-syntax/17373 "2022-09-11T20:45:32Z")\
**Posts on this page:** 3\
**Page:** 2

<div class="post-metadata">

**Author:** ![nokotto](https://avatars.discourse-cdn.com/v4/letter/n/f07891/32.png) [@nokotto](https://internals.rust-lang.org/u/nokotto)\
**Post date:** [September 14, 2022, 1:49pm UTC](https://internals.rust-lang.org/t/replace-if-let-syntax/17373/21 "2022-09-14T13:49:38Z")

</div>

> [@ekuber](#):
>
> What you want [is on its way to stable _for the case where you don't need the other variant's data_](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=15066a412ecf97774efd11cff9f5d5e4):
> 
> `let Some(data2) = opt else { log("failed"); return Err("Custom err"); };`

Those are good news.

The thing is one needs to capture the second variant of the data, due there is many functions that returns a `Result` or an `Option`, or even some libraries a `Result<Option>`. I mean sugars for `match` for dealing with monads.

Basically would be great being able to destructure as quickly and clean as possible the monads. I mean, to manage the possible errors or limits what returns a function, for proceeding to work with the data.

```rust
// this code is inside of a function, so have to use return if needed.

let Ok(data) = res else Err(e) { log(e); return Err("Custom err"); };

// And one starts working with data

let Ok(data) = res else Err(e) { log(e); default };

// And one starts working with data

```

.

One usually also wants to try a second way for assigning the data:

```rust
let Ok(data) = res else Err(e) { 

    res2 else Err(e2) {
              log(e, e2);
	      return Err("res and res2 failed"); 
   }
};

```

.

And sometimes things like this, trying to escape from `match` towers as much as possible:

```rust
let Ok(data2) = res else Err(e) { 

    match e {
       Errortypet1() =>
	   { 
			res2 else Err(e2){
				log(e, e2);
				return Err("failed res, tryed res2 and also failed"); 
			}
	   },
       Errortypet4() =>
	   { 
			opt2 else None {
				log(e, "none");
				return Err("res and opt failed"); 
			}
	   },
	   _ =>{ log("unknown error"); return Err("unknown error"); }
   }
};

// And one starts working with data

```

---

<div class="post-metadata">

**Author:** ![y86-dev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/y86-dev/32/9867_2.png) [@y86-dev](https://internals.rust-lang.org/u/y86-dev)\
**Post date:** [September 14, 2022, 2:14pm UTC](https://internals.rust-lang.org/t/replace-if-let-syntax/17373/22 "2022-09-14T14:14:04Z")

</div>

> [@nokotto](#):
>
> Basically would be great being able to destructure as quickly and clean as possible the monads. I mean, to manage the possible errors or limits what returns a function, for proceeding to work with the data.
> 
> ```rust
> // this code is inside of a function, so have to use return if needed.
> 
> let Ok(data) = res else Err(e) { log(e); return Err("Custom err"); };
> 
> // And one starts working with data
> 
> let Ok(data) = res else Err(e) { log(e); default };
> 
> // And one starts working with data
> 
> ```

I would use the following code pattern for that:

```rust
fn handle_input(input: Input) -> Result<(), CustomError> {
    let data = parse_data(input)?;

    // with default:
    let data = parse_data(input)
        .map_err(|e| { log(e); default })
        .into_ok_or_err();
}

fn parse_data(input: Input) -> Result<Data, ParseError> { /*...*/ }

impl From<ParseError> for CustomError {
    fn from(e: ParseError) -> CustomError {
        log(e);
        CustomError::new("Custom err")
    }
}

```

* * *

> [@nokotto](#):
>
> One usually also wants to try a second way for assigning the data:
> 
> ```rust
> let Ok(data) = res else Err(e) { 
> 
> res2 else Err(e2) {
> log(e, e2);
> return Err("res and res2 failed"); 
> }
> };
> 
> ```

Here I would use this:

```rust
let data = match res {
    Ok(data) => data,
    Err(e) => match res2 {
        Ok(data) => data,
        Err(e2) => {
            log(e);
            log(e2);
            return Err("res and res2 failed");
        }
    }
};

```

* * *

> [@nokotto](#):
>
> And sometimes things like this, trying to escape from `match` towers as much as possible:
> 
> ```rust
> let Ok(data2) = res else Err(e) { 
> 
> match e {
> Errortypet1() =>
> { 
> res2 else Err(e2){
> log(e, e2);
> return Err("failed res, tryed res2 and also failed"); 
> }
> },
> Errortypet4() =>
> { 
> opt2 else None {
> log(e, "none");
> return Err("res and opt failed"); 
> }
> },
> _ =>{ log("unknown error"); return Err("unknown error"); }
> }
> };
> 
> // And one starts working with data
> 
> ```

You can pattern match deeper into your types like this:

```rust
let Ok(data) = match res { 
    Ok(data) => data,
    Err(e@Errortypet1()) => match res2 {
        Ok(data) => data,
        Err(e2) => {
            log(e);
            log(e2);
            return Err("failed res, tryed res2 and also failed"); 
        }
    }
    Err(e@Errortypet4()) => match opt2 {
        // here one could use let-else
        Some(data) => data,
        None => {
            log(e, "none");
            return Err("res and opt failed"); 
        }
    },
    Err(_) => {
        log("unknown error");
        return Err("unknown error");
    }
};

```

---

<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:** [December 13, 2022, 2:14pm UTC](https://internals.rust-lang.org/t/replace-if-let-syntax/17373/23 "2022-12-13T14:14:19Z")

</div>

Closed on December 13, 2022, 2:14pm UTC

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

[Previous page](https://internals.rust-lang.org/t/replace-if-let-syntax/17373.md?page=1)
