Elvis operator for Rust

Hmm, that's not bad but I'm not sure it's better than a match, and also what does it do if the enum has more than two alternatives? The compiler tracks which variants are impossible in each block? I can see people writing

let StateA(thing) = arg else {
    let StateB(otherthing) = arg else {
        let StateC(thirdthing) = arg else {
            return None;
        }
        return process_3(thirdthing);
    }
    return process_2(otherthing);
}
return process_1(thing);

which would clearly be better as a match ... I suppose at some point diagnosing "you should have written this differently" becomes AI-hard :slight_smile:

(You know what, there's a teaching-materials issue here. I think I'll start a separate thread about that.)

2 Likes

Becomes ugly! Only nice for 2 alternatives :smiley:

There seems to be some appetite..

Not all errors should be reported. When a function, e.g. TryFrom::try_from, returns Err, this doesn't necessarily means that an error occurred. It just means that a type conversion was not possible.

Sometimes return or continue is the correct way to handle an error.

If you still want to log it, you can do .map_err(log_error) ?: continue

3 Likes

I would want an operator like this, I've written a lot of utility macros that essentially boil down to what is proposed here. To bikeshed of the specific syntax, I don't think it should be ?: because at a glance it looks just like the expression if statement <condition> ? <true_expr> : <false_expr> in other languages (C, JavaScript, etc), with one part omitted. It also doesn't help that in those languages it can serve a very similar purpose.

// Expression
const x = foo ? 5 : 0;
// With control flow
const y = x ? x: return;
2 Likes

When I first came across a ?: b it was explained to me as a shortcut for a ? a : b, except a is only evaluated once.

Because Rust doesn't have "the" tertiary ternary operator _ ? _ : _, I don't think there is too much danger of confusion here.

2 Likes

"ternary" operator. Meaning an operator that has 3 -arguments. It is often referred to as "THE ternary operator", but, really what it is is "A ternary operator that takes 3 arguments: boolean to check, value of type T if true, value of type T if false". So, if you were to have a "Boolean Ternary" operator in Rust, it would leverage a method of a "BooleanTernary" trait something like this:

trait BooleanTernary<T> {
  fn choose( &self : bool, trueValue : T, falseValue : T ) {
     if self { trueValue } else { falseValue }
  }
}

Except, this wouldn't actually be correct because it would unconditionally evaluate the trueValue and falseValue at the call-site. To be correct, it would have to take a lambda/expression producer for TRUE/FALSE values instead.

Because Rusts "if" statements are "expression", there really isn't a need for a "Boolean Ternary Operator" in Rust because let x = if test { truevalue } else { falsevalue } does exactly what the "Ternary" operator does in other languages.

NOTE: I'm only mentioning this for those who might be reading this and don't fully understand WHY Rust doesn't have (AND doesn't need) a Ternary operator.

3 Likes

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