&&= and ||=

Typescript 4.0 is introducing two new operators:

In Rust:

fn main() {
    let mut a = true;
    a &&= true;
    a ||= false;
}

In rare circumstances I wished to use this.

1 Like

Oddly enough, I wanted this here: https://github.com/rust-analyzer/rust-analyzer/pull/4587/files#diff-2d3440bb91de25b42566a44695daf55cR135

1 Like

Yes, it's not a super-common need, but once in a while I find a use for those operators. But I'm curious to know why Rust doesn't have them :slight_smile:

Operators like += are required to implement operations efficiently for non-primitive types like bigints, where a += b can be more efficient than a = a + b. But for || and &&, the first operand is necessarily a bool, so ||= is not as important to have as +=. My point is that although they can save typing an identifier in some cases, I don't think these operators would carry their weight.

5 Likes

Just for comparison: Rust does have &= and |= operators which work with bool, as well as numeric types and user-defined types. Of course, these don't have the short-circuiting behavior of && and ||, so they are usually not appropriate when the RHS is expensive to evaluate. (For example, you can't use them to simplify @matklad's example, above.)

3 Likes

As with any time people suggest a new punctuation token:

Unfortunately, this would be breaking for some macros (at least without "interesting" compat hacks between the actual token model and macro_rules!). (Or a new statement type <place> && = <expr> which would work but would also be.. "interesting.")

So I doubt the small motivation outweighs the cost of adding the new token (or otherwise making it work). At the very least it'd be a "next edition" kind of thing.

4 Likes

Well, if the LHS is costly to compute (e.g. it is a long expression) then this will save a lot. Normal compiled languages have common sub-expression elimination that can probably lift out the common LHS and just use a pointer to the location to mutate. However, JavaScript is not compiled.

I would be interested to see how this is implemented though, especially when LHS &&= RHS; where LHS involves property access that can potentially have side effects because the equivalent LHS = LHS && RHS is going to trip those side effects twice.

Maybe this is why it takes so long to show up.

1 Like

I guess that it creates a new variable if necessary, e.g.

a.b().c &&= d();
// becomes
const _temp = a.b();
_temp.c && (_temp.c = d());

If c is a property, both its getter and its setter might be called.

1 Like

There is a note in the announcement that says beware of property access with side effects.

It also says it is smart enough to handle complicated expressions on the LHS...