# Something about combinators

**URL:** <https://internals.rust-lang.org/t/something-about-combinators/17323>\
**Category:** language design\
**Created:** [September 2, 2022, 12:45pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323 "2022-09-02T12:45:39Z")\
**Posts on this page:** 15\
**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:** [September 2, 2022, 12:45pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/1 "2022-09-02T12:45:39Z")

</div>

It seems Rust combinators are not short circuited.

Is it possible to replace them with operators, and make them circuited?

i.e. a().or(b()) will always calculate b(), but a() | b(), if a is some, then b() is not calculated.

---

<div class="post-metadata">

**Author:** ![trentj](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/trentj/32/8551_2.png) [@trentj](https://internals.rust-lang.org/u/trentj)\
**Post date:** [September 2, 2022, 12:51pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/2 "2022-09-02T12:51:39Z")

</div>

`a().or_else(|_| b())`

---

<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:** [September 2, 2022, 1:04pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/3 "2022-09-02T13:04:44Z")

</div>

I know. but nor as elegant as a() | b(), don't you think?

Some javascript syntax sugar is really nice. 🙂

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [September 2, 2022, 1:16pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/5 "2022-09-02T13:16:00Z")

</div>

> [@cklein](#):
>
> a() | b(), if a is some, then b() is not calculated.

What do you mean by "some" here? Also, this is already bitwise-or and making operators mean completely different things based on their argument types sounds distinctly C++ in nature, not Rust-like.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [September 2, 2022, 1:48pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/6 "2022-09-02T13:48:18Z")

</div>

The operator you want is `||`, not `|`. The former is a logical or, which doesn't evaluate the right hand side if the left hand side evaluates to `true`, while the latter is a bitwise or, which always evaluates both sides. Thus it is expected for `|` to not shortcircuit.

Currently you can only overload the `|` operator because nobody has proposed a good design for a shortcircuiting overloadable `||` yet.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 2, 2022, 4:34pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/7 "2022-09-02T16:34:51Z")

</div>

If you want a concise version: `a().or(b)` where `b` is a function item type and `or` takes functions for the right hand side.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [September 2, 2022, 5:48pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/8 "2022-09-02T17:48:50Z")

</div>

In Rust's typical API "dialect" `or` takes values; `or_else` takes deferred values (usually a closure).

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [September 2, 2022, 6:01pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/9 "2022-09-02T18:01:06Z")

</div>

Sure, but if someone wants to write something optimized for conciseness AND shortcircuiting than they can do it that way.

---

<div class="post-metadata">

**Author:** ![lordan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lordan/32/2107_2.png) [@lordan](https://internals.rust-lang.org/u/lordan)\
**Post date:** [September 2, 2022, 6:54pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/10 "2022-09-02T18:54:20Z")

</div>

> [@mathstuf](#):
>
> making operators mean completely different things based on their argument types sounds distinctly C++ in nature, not Rust-like

`+` being used for addition as well as concatenation is a pet peeve of mine! 😑

---

<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:** [September 2, 2022, 8:02pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/11 "2022-09-02T20:02:29Z")

</div>

> [@SkiFire13](#):
>
> Currently you can only overload the `|` operator because nobody has proposed a good design for a shortcircuiting overloadable `||` yet.

I think we have at least one that _could_ reasonably be used. There are some [from when this was previously discussed](https://github.com/rust-lang/rfcs/pull/2722#discussion_r302787137), for example.

In some ways, [`?` is sugar for `&&`](https://github.com/rust-lang/rfcs/pull/2722#issuecomment-832934891), but we have zero sugar for `||`-like things, so I think it would make sense for Rust to eventually have _something_ along those lines.

But I agree we don't yet know what that _should_ be.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [September 2, 2022, 8:08pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/12 "2022-09-02T20:08:00Z")

</div>

> [@scottmcm](#):
>
> so I think it would make sense for Rust to eventually have _something_ along those lines.

Well, there are `¿`, `⸘`, `‽`, or `⸮` available for those 😛 .

---

<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:** [September 2, 2022, 8:31pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/13 "2022-09-02T20:31:34Z")

</div>

> [@mathstuf](#):
>
> there are `¿`, `⸘`, `‽`, or `⸮` available for those

I suspect you say that at least partially in jest, but it raises something I think is important:

_The or-sugar's structure should probably be very different from that of the and-sugar._

[`Option::zip`](https://doc.rust-lang.org/std/option/enum.Option.html#method.zip) works great with `?`: it's just `try { (a?, b?) }`.

But ignoring whether the specific token is good for now, what would it mean to write an "or form" of that? How do I think about `(a¿, b¿)`? Is there any semantics we could give that that make any sense at all?

Just doing the opposite of `?`, and short-circuiting with the some value but having the expression give `None` is weird, since the `None` is straight-up useless, and might as well be `()` instead. But then making that tuple is also pointless, since you're getting a `((), ())` that you need to handle.

The or-equivalent of `zip` is something like `(Option<A>, Option<B>)` → `Option<EitherOrBoth<A, B>>`, I guess? (Using [https://docs.rs/itertools/latest/itertools/enum.EitherOrBoth.html.](https://docs.rs/itertools/latest/itertools/enum.EitherOrBoth.html.))

Or, from a more philosophical view, `?` works great because you can read through for the "happy" path first, then investigate all those error returns in a second pass. Whereas if you were to try to read something ignoring the `¿`s, it'd make no sense.

But while that has me convinced that postfix-operator isn't the best form for it, I'm still not sure what is. Maybe it's just a macro, like

```rust
coalesce![
    first() + attempt(),
    some_other().approach,
    get_the.fallback(),
]

```

Or the other things that's conceptually a "try stuff in order until one works" construct is `match`, so maybe that can offer some kind of inspiration?

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [September 4, 2022, 11:27am UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/14 "2022-09-04T11:27:42Z")

</div>

> [@scottmcm](#):
>
> I suspect you say that at least partially in jest

Indeed.

> [@scottmcm](#):
>
> ```rust
> coalesce![
> first() + attempt(),
> some_other().approach,
> get_the.fallback(),
> ]
> 
> ```

This only works if it is lazy (probably wrapped up in lambdas though that certainly introduces "fun" hidden moves or sharing inside the macro). I certainly wouldn't want `get_the.fallback()` to be called unless the other two have already failed.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [September 4, 2022, 2:55pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/15 "2022-09-04T14:55:15Z")

</div>

Since it's a macro no lambdas would be needed, it can expand to something like

```rust
if let Some(v) = first() + attempt() {
  v
} else if let Some(v) = some_other().approach {
  v
} else {
  get_the.fallback()
}

```

---

<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 3, 2022, 2:55pm UTC](https://internals.rust-lang.org/t/something-about-combinators/17323/16 "2022-12-03T14:55:50Z")

</div>

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