# Or operator on options

**URL:** <https://internals.rust-lang.org/t/or-operator-on-options/18515>\
**Category:** Uncategorized\
**Created:** [March 13, 2023, 1:32am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515 "2023-03-13T01:32:26Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 13, 2023, 1:32am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/1 "2023-03-13T01:32:26Z")

</div>

I want to be able to say:

optionastatement || optionbstatement

is there anyway to achieve this? or\_else won't cut it for obvious reasons.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [March 13, 2023, 2:11am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/2 "2023-03-13T02:11:18Z")

</div>

There's no way to do that yet. There have been past suggestions of a trait like `LogicalOr`, but those have had drawbacks that (_I'm guessing_) are similar to what you don't like about `or_else`. Still, please do specify what you think those "obvious" reasons are.

---

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 13, 2023, 2:25am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/3 "2023-03-13T02:25:45Z")

</div>

1. Variable scope
2. I can’t have ? Operator on a result in optionbstatement if it is a closure even my enclosing function returns a result

---

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 13, 2023, 2:40am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/4 "2023-03-13T02:40:14Z")

</div>

Besides, or\_else looks really ugly:-) a || b is really elegant Maybe come up an official macro would do the job too.

---

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 13, 2023, 3:43am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/5 "2023-03-13T03:43:14Z")

</div>

I just realize that there are no logical operator traits in Rust. Maybe it is on purpose? Logical operators are hard to mimic?

---

<div class="post-metadata">

**Author:** ![zirconium-n](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zirconium-n/32/9078_2.png) [@zirconium-n](https://internals.rust-lang.org/u/zirconium-n)\
**Post date:** [March 13, 2023, 3:49am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/6 "2023-03-13T03:49:12Z")

</div>

> [@cklein](#):
>
> Logical operators are hard to mimic?

It's not clear how does it interreact with short circuiting.

> [@cklein](#):
>
> I want to be able to say:
> 
> optionastatement || optionbstatement

What's the desired semantic? Can you provide a desugar-ed code?

---

<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:** [March 13, 2023, 4:20am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/7 "2023-03-13T04:20:49Z")

</div>

We _could_ attach this to `Try` now, where `$a || $b` becomes

```rust
match Try::branch($a) {
    ControlFlow::Continue(a) => Try::from_output(a),
    ControlFlow::Break(_) => $b,
}

```

(likely with the same "same residual" inference rules as `try` blocks are likely getting).

Given an `invert_try<T: Try>(_: T) -> impl Try<Output=T::Residual, Residual=T::Output>`, then `$a || $b` can be written as `uninvert_try(try { invert_try($a)?; invert_try($b)? })` (though ofc this introduces a new `?` boundary that cklein would like to avoid).

If you also allow `$a && $b` as a shorthand for `try { $a?; $b? }` and `$a ?: $b` for `($a || try{$b}).unwrap()` (both in `match` form), then `&&`/`||`/`?:` become very powerful generic monadic combinators if you're discarding the residual.

However, these are (like monads) so general to the point of having unclear benefit. Even when you're fully monad wise, nested monads (i.e. using `?` to break from the fn from expressions being monad applied with `||`) are hard to wrap your head around.

I personally think an easy method for `Option<T> -> ControlFlow<T>` (essentially `invert_try` for `Option`) makes sense, so that the OP's `$a || $b` can be written as e.g. `try { $a.then_break()?; $b.then_break()? }.break_value()` makes sense, but going further to `&&`/`||`/`?:` goes a bit too far beyond what Rust wants to encourage. (Not the least because these encourage ignoring the residual, whereas the purpose of `?` is in major part to encourage _not_ discarding the residual.)

Aside: this makes me wonder whether the macro hygiene of `break`/`continue`/`return`/`?`/etc. sh/could've included the break label/target, such that macros can't change their target. I've defensively written `unsafe`-using macros in awkward ways\[1\] to avoid the user code to interfere, before.

* * *

1. The simplest and completest is just to put the user code in an immediately-invoked closure. The fancier way is to write something along the lines of

---

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 13, 2023, 5:29am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/8 "2023-03-13T05:29:10Z")

</div>

A?.B | c?.d Assume my enclosing function return an anyhow result

Now if I use or\_else, I would have to put c?.d in closure, it won’t work. Or else can do short circuiting, but closure does not have the same scope as statement

---

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 13, 2023, 8:08am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/9 "2023-03-13T08:08:57Z")

</div>

I finally created a fallback! macro myself to do the job. hope it gets into std. 🙂

```rust
macro_rules! fallback {
    ($a:expr) => { $a };
    ($a:expr, $($b:expr),*) => {if let Some(x) = $a { x } else { fallback!($($b),*) } };
}

```

---

<div class="post-metadata">

**Author:** ![simonbuchan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/simonbuchan/32/9390_2.png) [@simonbuchan](https://internals.rust-lang.org/u/simonbuchan)\
**Post date:** [March 13, 2023, 8:29am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/10 "2023-03-13T08:29:28Z")

</div>

I generally use `a.ok().and_then(|a| b)?` or `a.ok().or_else(|| b)?` if I want to do some fallible stuff in `b`, but it's still clumsy.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [March 13, 2023, 6:22pm UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/11 "2023-03-13T18:22:19Z")

</div>

> [@cklein](#):
>
> `macro_rules! fallback`

You might also be interested in this (very old) thread: [Something for coalescing; aka generalized/improved `or_else`](https://internals.rust-lang.org/t/something-for-coalescing-aka-generalized-improved-or-else/9295)

---

<div class="post-metadata">

**Author:** ![cklein](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cklein/32/10656_2.png) [@cklein](https://internals.rust-lang.org/u/cklein)\
**Post date:** [March 16, 2023, 1:23am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/12 "2023-03-16T01:23:28Z")

</div>

std::ops::Try is not stable after so many years, I don't think it will ever make into stable release. There must be something seriously wrong.

---

<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:** [June 14, 2023, 1:23am UTC](https://internals.rust-lang.org/t/or-operator-on-options/18515/13 "2023-06-14T01:23:54Z")

</div>

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