New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ternary operator #1698

Closed
brson opened this Issue Jan 28, 2012 · 29 comments

Comments

Projects
None yet
@brson
Contributor

brson commented Jan 28, 2012

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.

@catamorphism

This comment has been minimized.

Show comment
Hide comment
@catamorphism

catamorphism Jan 28, 2012

Contributor

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

Contributor

catamorphism commented Jan 28, 2012

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

@BrendanEich

This comment has been minimized.

Show comment
Hide comment
@BrendanEich

BrendanEich Jan 28, 2012

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

BrendanEich commented Jan 28, 2012

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

@kevina

This comment has been minimized.

Show comment
Hide comment
@kevina

kevina Jan 29, 2012

Contributor

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.

Contributor

kevina commented Jan 29, 2012

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.

@ssylvan

This comment has been minimized.

Show comment
Hide comment
@ssylvan

ssylvan Jan 29, 2012

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".

ssylvan commented Jan 29, 2012

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".

@kevina

This comment has been minimized.

Show comment
Hide comment
@kevina

kevina Jan 29, 2012

Contributor

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.

Contributor

kevina commented Jan 29, 2012

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.

@marijnh

This comment has been minimized.

Show comment
Hide comment
@marijnh

marijnh Jan 29, 2012

Contributor

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.

Contributor

marijnh commented Jan 29, 2012

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.

@kud1ing

This comment has been minimized.

Show comment
Hide comment
@kud1ing

kud1ing Jan 29, 2012

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

kud1ing commented Jan 29, 2012

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

@nikomatsakis

This comment has been minimized.

Show comment
Hide comment
@nikomatsakis

nikomatsakis Jan 30, 2012

Contributor

@marijnh ++ :)

Contributor

nikomatsakis commented Jan 30, 2012

@marijnh ++ :)

@graydon

This comment has been minimized.

Show comment
Hide comment
@graydon

graydon Jan 30, 2012

Contributor

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

Contributor

graydon commented Jan 30, 2012

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

@marijnh

This comment has been minimized.

Show comment
Hide comment
@marijnh

marijnh Jan 31, 2012

Contributor

This was done in pull req #1705.

Contributor

marijnh commented Jan 31, 2012

This was done in pull req #1705.

@marijnh marijnh closed this Jan 31, 2012

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp May 1, 2014

    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.

caitp commented May 1, 2014

    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.

@rkyoku

This comment has been minimized.

Show comment
Hide comment
@rkyoku

rkyoku Oct 10, 2015

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.

rkyoku commented Oct 10, 2015

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.

@singpolyma

This comment has been minimized.

Show comment
Hide comment
@singpolyma

singpolyma Oct 11, 2015

I also miss this syntax

singpolyma commented Oct 11, 2015

I also miss this syntax

@loveencounterflow

This comment has been minimized.

Show comment
Hide comment
@loveencounterflow

loveencounterflow Oct 23, 2015

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.

loveencounterflow commented Oct 23, 2015

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.

@kdr213

This comment has been minimized.

Show comment
Hide comment
@kdr213

kdr213 Oct 23, 2015

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

kdr213 commented Oct 23, 2015

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

@drbawb

This comment has been minimized.

Show comment
Hide comment
@drbawb

drbawb Oct 23, 2015

@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

drbawb commented Oct 23, 2015

@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

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 23, 2015

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

caitp commented Oct 23, 2015

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

@drbawb

This comment has been minimized.

Show comment
Hide comment
@drbawb

drbawb Oct 23, 2015

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.

drbawb commented Oct 23, 2015

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.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 23, 2015

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

caitp commented Oct 23, 2015

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

@mitchmindtree

This comment has been minimized.

Show comment
Hide comment
@mitchmindtree

mitchmindtree Oct 23, 2015

Contributor
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)
Contributor

mitchmindtree commented Oct 23, 2015

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)
@loveencounterflow

This comment has been minimized.

Show comment
Hide comment
@loveencounterflow

loveencounterflow commented Oct 23, 2015

@mitchmindtree totally.

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 23, 2015

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); }

caitp commented Oct 23, 2015

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); }

@retep998

This comment has been minimized.

Show comment
Hide comment
@retep998

retep998 Oct 23, 2015

Member

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.

Member

retep998 commented Oct 23, 2015

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.

@mitchmindtree

This comment has been minimized.

Show comment
Hide comment
@mitchmindtree

mitchmindtree Oct 23, 2015

Contributor

@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 😸 )

Contributor

mitchmindtree commented Oct 23, 2015

@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 😸 )

@caitp

This comment has been minimized.

Show comment
Hide comment
@caitp

caitp Oct 23, 2015

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

caitp commented Oct 23, 2015

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

@kevina

This comment has been minimized.

Show comment
Hide comment
@kevina

kevina Oct 24, 2015

Contributor

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?

Contributor

kevina commented Oct 24, 2015

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?

@rkyoku

This comment has been minimized.

Show comment
Hide comment
@rkyoku

rkyoku Oct 24, 2015

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

Le sam. 24 oct. 2015 02:46, Kevin Atkinson notifications@github.com 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
#1698 (comment).

rkyoku commented Oct 24, 2015

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

Le sam. 24 oct. 2015 02:46, Kevin Atkinson notifications@github.com 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
#1698 (comment).

@kevina

This comment has been minimized.

Show comment
Hide comment
@kevina

kevina Oct 24, 2015

Contributor

@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}.

Contributor

kevina commented Oct 24, 2015

@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}.

@bklooste

This comment has been minimized.

Show comment
Hide comment
@bklooste

bklooste Nov 9, 2015

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
 }      

bklooste commented Nov 9, 2015

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
 }      
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment