Rust: Remove ternary operator

Created on 29 Jan 2012  ·  29Comments  ·  Source: rust-lang/rust

One of the comments that stuck with me after the 0.1 announcement was somebody asking why we have a ternary operator, since it is functionally the same as our if expressions. I'm sympathetic to this sentiment

Lately I have been feeling wary about the rapid addition of features to the language and think that we should be more cautious about committing to things we don't really need. One of the original mandates upon the announcement of Rust was to focus on removing features (it's in the language FAQ), and I don't think there's any way to argue that we have succeeded at that.

Admittedly, the ternary operator is a low-maintenance feature, but its removal is also low-impact.

A-frontend E-easy

Most helpful comment

Agreed. Wish I had made JS an expression language. The great statement/expression split motivates ?: but Rust is free of that, and if-else suffices.

/be

All 29 comments

I agree. I was wondering why we had the ternary operator, too.

Agreed. Wish I had made JS an expression language. The great statement/expression split motivates ?: but Rust is free of that, and if-else suffices.

/be

As a very heavy user of the ?: operator in C/C++ I prefer the compact syntax. I also think it formats better when the expression is too long to fit on a single line:

let x = some_very_long_condational
     ? if_true
     : if_false

let x = if some_very_long_condational 
     { if_true}
     else { if_false}

The syntax can get worse, in my view, if if_true and if_false won't fit on a single line. For example, where should the braces be placed.

Just my two cents.

I like:

let x = if some_very_long_condational { 
                 if_true
           } else { 
                 if_false
           }

It adds some extra lines (the "else line" and the final bracket), but it keeps it clean and you can add as much code as you want in either.

I use the ternary operator a lot in C++, but I think the syntax is poor. You ave to spot the ? and : in the middle of a sea of other tokens to see that it's even a conditional. With expression-if you have the leading token indicating to the reader "here comes a conditional".

Well I still prefer the syntax of the ?: operator. I find your choice of formatting too verbose, especially for the simple cases when if_true and if_false are a single expressions (as oppose to multiple statements ending in an expression).

Nevertheless, I won't object very strongly if the ?: operator is removed.

I'm also using ?: all over the place, but I still think removing it would be a good idea -- it frees up two (!) ASCII sigils in our expression syntax. Think of all the other awesomely cryptic things we could do with them.

A non-cryptic use would be to allow them as part of the predicate name.
E.g. "empty?()" instead of "is_empty()".

@marijnh ++ :)

Personally I don't give a hoot. Igor argued for ternary back in https://mail.mozilla.org/pipermail/rust-dev/2010-November/000110.html

This was done in pull req #1705.

    return parent.index_of(child_a) < offset_b ? -1 : 1

looks infinitely better than

    return if parent.index_of(child_a) < offset_b {
        -1 
    } else {
        1
    }

If we have to be pythony about this,

return -1 if parent.index_of(child_a) < offset_b else 1

would be much better.

I agree, I don't get it why it had to be removed... Please do not force Rust users to write unnecessarily heavy/verbose code, when such a common practice (ternary operator) exists in most if not all languages.

Anyway, it is done, but I just wanted to add my voice to those supporting a cleaner code style.

I also miss this syntax

I think there are three conspiring effects at work here, viz

1) "The great statement/expression split" (@BrendanEich);
2) Coercion of non-Booleans in Boolean contexts;
3) Even 'dynamic' languages don't commonly get 'dynamic syntax' (real macros) and 'dynamic semantics' (a la Python's from __future__ import division) these days.

(1) means that if ... then ... else ... is sth fundamentally different from ... ? ... : ..., which is an entirely dispensable distinction. There are edge cases like return, but overall the distinction is not needed.

(2) means that you can, in many languages, use arbitrary expressions as tests; this looks only convenient as long as you're still using your first language and gets annoying as soon as you start with your second. As pointed out above on this reddit discussion, it's not clear why an empty list should denote either false or true—just write if ( d.length == 0 ) ... and you gained _so_ much clarity!

(3) means you're stuck with whatever the language committee gives you, and whatever that is, the language will likely be stuck with it until someone comes along, forks or rewrites the codebase and gives it a new name. It could be different; there could be languages that allow, say, use 'ternary conditions'; use 'empty lists are false';. There are precedents for that. Of course, a lot of things speak against such flexibility because you will always have to keep in mind those "deviation markers" and remember to copy them when you copy-and-paste program. OTOH if mere users could change language syntax and semantics easily and prepackage such practices into installable modules, that could greatly help in the evolution of the language.

@kevina Sometimes verbosity isn't a bad thing, but I agree that ternary operators clean up code very nicely.

@caitp: what exactly is wrong with?

return if parent.index_of(child_a) < offset_b { -1 } else { 1 }

or one of my personal favorites "hugging clauses"

return 
    if parent.index_of(child_a) < offset_b { -1 } 
    else                                   {  1 }

... or use a match, especially if there's multiple conditions ...

return match parent.index_of(child_a) < offset_by {
  true  => -1,
  false => 1
}

... and of course if it's likely to be reused: just move it into a function ...

return parent.is_child_before(offset_b)

Look at that... you have options... because _everything_ is an expression.

Never in rust have I wanted to save the _six characters_ it takes to write if {} else {} instead of
() ? :, plus chaining additional conditionals looks much nicer with if-as-an-expression. (Nested ternary operators become messy very quickly.)

In my opinion: when using if-as-an-expression I don't see the need to inject so much unnecessary whitespace. I also find it reads more naturally than the ternary operator, and the additional verbosity helps to separate the two clauses visually. That's just my $0.02

I think you may have misread what I said (and note that this was some time ago)

I'm merely pointing out I don't see how the ternary operator in any way looks "infinitely better."
In my opinion common forms are infinitely more beautiful than special case forms.

The comment is saying that sometimes, conditionals-as-expressions are very useful, as opposed to conditional statements. Dropping the hugging braces is only subjectively an improvement

return parent.index_of(child_a) < offset_b ? -1 : 1

vs

return if parent.index_of(child_a) < offset_b { -1 } else { 1 }

@caitp is the second here really infinitely worse than the first? Rust's if else is still an expression (not a statement).

My thoughts are:

  • The second seems like it would be more readable to someone without a history of other languages and
  • We would probably be better off keeping the ? syntax up our sleeves for future sugar (perhaps related to Option, etc)

@mitchmindtree totally.

Again, you're misunderstanding what the comment was saying.

return if parent.index_of(child_a) < offset_b { -1 } else { 1 } is still evaluating the conditional as an expression (and is thus able to be an operand for return).

The braces are ugly, but the main point is about conditional expressions, not about braces. It's about being able to write return foo.bar.baz(<conditional operand>) versus if (<conditional operand>) { return foo.bar.baz(1); } else { return foo.bar.baz(2); }

I think what we really need to realize is that this issue is over three years old. Considering people haven't really missed ternaries that much in three years, I think it is safe to say that they will stay removed.

@caitp hmm I'm still not sure i'm following. Are you talking about rust in particular? Or just statements vs expressions in general?

In rust you can still do

return foo.bar.baz(if cond { 42 } else { 0 })

? (I'm aware you weren't talking about braces btw, sorry for the confusion :smile_cat: )

At the time, in ToT, there was no way to do this in Rust.

I don't have a strong opinion, but I just want to add that if ? and : can better be used for other things, why not use something like ?? and ?: instead, for example cond ?? 43 ?: 0?

Why change the way developers have been used to for dozens of years?

Le sam. 24 oct. 2015 02:46, Kevin Atkinson [email protected] a
écrit :

I don't have a strong opinion, but I just want to add that is ? and : can
better be used for other thanking why not use something like ?? and ?:
instead. so maybe cond ?? 43 ?: 0.


Reply to this email directly or view it on GitHub
https://github.com/rust-lang/rust/issues/1698#issuecomment-150728625.

@RenaudParis Sorry, what I meant to say was: I don't have a strong opinion, but I just want to add that if ? and : can better be used for other things, why not use something like ?? and ?: instead, for example cond ?? 43 ?: 0?

One of the reasons the ternary operator was removed was so that "?" could be used for something else in the future. My suggestion was to use another operator. cond ?? 43 ?: 0 is still shorter than if cond {43} else {0}.

I think its correct to be removed however It would not be so bad if bracers were not required for single expression. ( And yes i know how much of a pain this is in the parser it is imho well worth it - readability is very important )

eg

if i ==0 
     return i
else 
      1  

or even

if i == 0  return i
    else 1  

This format is better than

 if i == 0   ? return i
      : 1  

or

if i == 0   
      ? return i 
      : 1  

verses

if i ==0 {
      return i
}
else {
    1
}      

pretty ugly / hard to read for something so common .

It gets worse but easier to read if you have a dev policy against Egyptian braces.

if i ==0
{
     return i
}
else
{
     1
 }      
Was this page helpful?
0 / 5 - 0 ratings