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

Rust Needs The Ternary Conditional Operator (-?-:-) #1362

Closed
dangerrust opened this Issue Nov 10, 2015 · 48 comments

Comments

Projects
None yet
@dangerrust

dangerrust commented Nov 10, 2015

Hello,

It looks like Rust forgot to implement the ternary conditional operator

It's operator that looks like this: condition ? trueExpression : falseExpression

This important feature lets you do things like return value == 5 ? success : failure;

Without this Ternary Conditional Operator you must use if statements which make ugly duplicated code (leads to bugs)

I think it easy to add support for this in Rust

@dscorbett

This comment has been minimized.

Show comment
Hide comment
@dscorbett

dscorbett Nov 10, 2015

Rust already has this: return if value == 5 { success } else { failure }.

dscorbett commented Nov 10, 2015

Rust already has this: return if value == 5 { success } else { failure }.

@dangerrust

This comment has been minimized.

Show comment
Hide comment
@dangerrust

dangerrust Nov 10, 2015

@dscorbett That does not look very nice

dangerrust commented Nov 10, 2015

@dscorbett That does not look very nice

@pnkfelix

This comment has been minimized.

Show comment
Hide comment
@pnkfelix

pnkfelix Nov 10, 2015

Member

I have been very happy with our if-expression syntax. Not everyone loves the ternary-?:

Member

pnkfelix commented Nov 10, 2015

I have been very happy with our if-expression syntax. Not everyone loves the ternary-?:

@nagisa

This comment has been minimized.

Show comment
Hide comment
@nagisa

nagisa Nov 10, 2015

Contributor

-1.

Contributor

nagisa commented Nov 10, 2015

-1.

@pnkfelix

This comment has been minimized.

Show comment
Hide comment
@pnkfelix

pnkfelix Nov 10, 2015

Member

(Downgrading so-called "importance")

Member

pnkfelix commented Nov 10, 2015

(Downgrading so-called "importance")

@Gankro

This comment has been minimized.

Show comment
Hide comment
@Gankro

Gankro Nov 10, 2015

Contributor

I continue to be against ever adding the ternary.

Contributor

Gankro commented Nov 10, 2015

I continue to be against ever adding the ternary.

@pnkfelix pnkfelix changed the title from Important: Rust Needs The Ternary Conditional Operator to Rust Needs The Ternary Conditional Operator (-?-:-) Nov 10, 2015

@jonas-schievink

This comment has been minimized.

Show comment
Hide comment
@jonas-schievink

jonas-schievink Nov 10, 2015

Contributor

👎 We have if ... else, which does the same thing and is more readable IMO

Contributor

jonas-schievink commented Nov 10, 2015

👎 We have if ... else, which does the same thing and is more readable IMO

@brendanzab

This comment has been minimized.

Show comment
Hide comment
@brendanzab

brendanzab Nov 11, 2015

Member

Sorry, but 👎 from me too. I sympathise with the argument for terseness, but would rather we not duplicate the functionality of if/else.

Member

brendanzab commented Nov 11, 2015

Sorry, but 👎 from me too. I sympathise with the argument for terseness, but would rather we not duplicate the functionality of if/else.

@bstrie

This comment has been minimized.

Show comment
Hide comment
@bstrie

bstrie Nov 11, 2015

Contributor

Rust tries to avoid having multiple ways to do the same thing. Furthermore, the : symbol is already more overloaded than I would like, and classic ternary syntax would be grammatically ambiguous with the already-accepted type ascription RFC. Furtherfurthermore, there are vague plans to use the ? symbol for language-level error-handling support in the future.

Contributor

bstrie commented Nov 11, 2015

Rust tries to avoid having multiple ways to do the same thing. Furthermore, the : symbol is already more overloaded than I would like, and classic ternary syntax would be grammatically ambiguous with the already-accepted type ascription RFC. Furtherfurthermore, there are vague plans to use the ? symbol for language-level error-handling support in the future.

@graydon

This comment has been minimized.

Show comment
Hide comment
@graydon

graydon Nov 12, 2015

We added ternary at one point strictly to satisfy this aesthetic preference, and then later removed it due to deciding it didn't carry its weight.

Following the famous "time traveller rule of 3", one should only backtrack on such a decision at most twice; three times risks the integrity of spacetime.

graydon commented Nov 12, 2015

We added ternary at one point strictly to satisfy this aesthetic preference, and then later removed it due to deciding it didn't carry its weight.

Following the famous "time traveller rule of 3", one should only backtrack on such a decision at most twice; three times risks the integrity of spacetime.

@frewsxcv

This comment has been minimized.

Show comment
Hide comment
@frewsxcv

frewsxcv Nov 12, 2015

Member

👎

I think if..else is more readable than dedicated ternary symbols

Member

frewsxcv commented Nov 12, 2015

👎

I think if..else is more readable than dedicated ternary symbols

@nikomatsakis

This comment has been minimized.

Show comment
Hide comment
@nikomatsakis

nikomatsakis Nov 12, 2015

Contributor

👎

EDIT: Sorry, I don't usually like being so terse, so let me just expand a touch. We have if/else, which is perfectly readable, and ternary just doesn't come up that often that it merits two similar bits of syntax. Also, I find very frequently I wind up using match or if let instead of a simple boolean expression, and I like the fact that which ever form of "ternary-like" thing I am using, it looks roughly the same. Basically, not needing a ternary expression is one of the great things about having an expression-oriented language!

Contributor

nikomatsakis commented Nov 12, 2015

👎

EDIT: Sorry, I don't usually like being so terse, so let me just expand a touch. We have if/else, which is perfectly readable, and ternary just doesn't come up that often that it merits two similar bits of syntax. Also, I find very frequently I wind up using match or if let instead of a simple boolean expression, and I like the fact that which ever form of "ternary-like" thing I am using, it looks roughly the same. Basically, not needing a ternary expression is one of the great things about having an expression-oriented language!

@pnkfelix

This comment has been minimized.

Show comment
Hide comment
@pnkfelix
Member

pnkfelix commented Nov 12, 2015

@tshepang

This comment has been minimized.

Show comment
Hide comment
@tshepang

tshepang Nov 13, 2015

Contributor

I am grateful that this was removed, so 👎

Contributor

tshepang commented Nov 13, 2015

I am grateful that this was removed, so 👎

@AngusP

This comment has been minimized.

Show comment
Hide comment
@AngusP

AngusP Nov 17, 2015

There's a lot of subjectivity in whether the ternary operator is a good idea or not; But not everyone has to want a feature for it to be worth including. C, C++, and a bunch of other languages have this generally useful feature.

The syntax is also similar to the match we already have:

match token {
        '+' => accumulator += 1,
        '-' => accumulator -= 1,
        _ => { /* ignore everything else */ }
}

Which is of the form condition => expression if true, stuff to do if false

return foo == 1 ? 0 : 1;

is also in the form condition ? expression if true : expression if false;

Having the ternary operator allows the programmer the choice to use verbose ifs and elses or ?: which in my opinion if a good choice to leave open.

With that being said, we probably shouldn't use the same syntax as C given the use of ':' to indicate types and with associated functions, we could instead (as a suggestion) have the syntax

return foo == 1 => 0, 1;

AngusP commented Nov 17, 2015

There's a lot of subjectivity in whether the ternary operator is a good idea or not; But not everyone has to want a feature for it to be worth including. C, C++, and a bunch of other languages have this generally useful feature.

The syntax is also similar to the match we already have:

match token {
        '+' => accumulator += 1,
        '-' => accumulator -= 1,
        _ => { /* ignore everything else */ }
}

Which is of the form condition => expression if true, stuff to do if false

return foo == 1 ? 0 : 1;

is also in the form condition ? expression if true : expression if false;

Having the ternary operator allows the programmer the choice to use verbose ifs and elses or ?: which in my opinion if a good choice to leave open.

With that being said, we probably shouldn't use the same syntax as C given the use of ':' to indicate types and with associated functions, we could instead (as a suggestion) have the syntax

return foo == 1 => 0, 1;
@BurntSushi

This comment has been minimized.

Show comment
Hide comment
@BurntSushi

BurntSushi Nov 17, 2015

Member

Having the ternary operator allows the programmer the choice to use verbose ifs and elses or ?: which in my opinion if a good choice to leave open.

I disagree. Because that now means others will have to read that code. Sometimes fewer choices are better than more choices.

I'm with most others: big 👎 on this.

Member

BurntSushi commented Nov 17, 2015

Having the ternary operator allows the programmer the choice to use verbose ifs and elses or ?: which in my opinion if a good choice to leave open.

I disagree. Because that now means others will have to read that code. Sometimes fewer choices are better than more choices.

I'm with most others: big 👎 on this.

@AngusP

This comment has been minimized.

Show comment
Hide comment
@AngusP

AngusP Nov 17, 2015

Systems programmer should be very familiar with ?; give we've been using C and it's derivatives since the early 1970s. And you can't make the argument that it's confusing for beginners because Rust has other completely foreign notions like lifetimes, closures and patterns. So the problem is really just personal preference, and yes you can choose to never use the ternary operator but to be honest I was surprised it wasn't already in the language, coming from a C background.

Rust already has a lot of choices; you can specify types, or let the compiler infer them.
The ternary operator is also not the same thing as if (...) { thing } else { thing }, you can't (at least in most implementations) have more than one expression as 'thing' in a condition ? thing : thing;
Apparently you can, in some cases. Woops and thanks @arielb1

AngusP commented Nov 17, 2015

Systems programmer should be very familiar with ?; give we've been using C and it's derivatives since the early 1970s. And you can't make the argument that it's confusing for beginners because Rust has other completely foreign notions like lifetimes, closures and patterns. So the problem is really just personal preference, and yes you can choose to never use the ternary operator but to be honest I was surprised it wasn't already in the language, coming from a C background.

Rust already has a lot of choices; you can specify types, or let the compiler infer them.
The ternary operator is also not the same thing as if (...) { thing } else { thing }, you can't (at least in most implementations) have more than one expression as 'thing' in a condition ? thing : thing;
Apparently you can, in some cases. Woops and thanks @arielb1

@BurntSushi

This comment has been minimized.

Show comment
Hide comment
@BurntSushi

BurntSushi Nov 17, 2015

Member

Sometimes fewer choices are better than more choices. I believe it to be true in this case. That Rust sometimes gives choices is not an argument in favor of always having more choices.

I don't mind admitting it's personal preference. I've read enough ternary spaghetti in my time to know it's not the kind of spaghetti I want to consume.

Member

BurntSushi commented Nov 17, 2015

Sometimes fewer choices are better than more choices. I believe it to be true in this case. That Rust sometimes gives choices is not an argument in favor of always having more choices.

I don't mind admitting it's personal preference. I've read enough ternary spaghetti in my time to know it's not the kind of spaghetti I want to consume.

@arielb1

This comment has been minimized.

Show comment
Hide comment
@arielb1

arielb1 Nov 17, 2015

Contributor

@ArgusP

You certainly can have multiple expressions.

int main() {
    int x;
    return 1>0 ? ({ x=1; x; }): 2;
}
Contributor

arielb1 commented Nov 17, 2015

@ArgusP

You certainly can have multiple expressions.

int main() {
    int x;
    return 1>0 ? ({ x=1; x; }): 2;
}
@comex

This comment has been minimized.

Show comment
Hide comment
@comex

comex Nov 17, 2015

(That's a GNU extension.)

comex commented Nov 17, 2015

(That's a GNU extension.)

@AngusP

This comment has been minimized.

Show comment
Hide comment
@AngusP

AngusP Nov 17, 2015

@BurntSushi I absolutely understand where you're coming from, I'd gladly throw the K&R book at anyone who nested the ternary operator or used it for anything that warranted a verbose if else statement. But still, some of us want it so why not?

AngusP commented Nov 17, 2015

@BurntSushi I absolutely understand where you're coming from, I'd gladly throw the K&R book at anyone who nested the ternary operator or used it for anything that warranted a verbose if else statement. But still, some of us want it so why not?

@sfackler

This comment has been minimized.

Show comment
Hide comment
@sfackler

sfackler Nov 17, 2015

Member

It is not particularly sustainable to support the union of all functionality that anyone has ever wanted.

Member

sfackler commented Nov 17, 2015

It is not particularly sustainable to support the union of all functionality that anyone has ever wanted.

@BurntSushi

This comment has been minimized.

Show comment
Hide comment
@BurntSushi

BurntSushi Nov 17, 2015

Member

I don't think any new syntax should be added under the justification of "why not."

Member

BurntSushi commented Nov 17, 2015

I don't think any new syntax should be added under the justification of "why not."

@ticki

This comment has been minimized.

Show comment
Hide comment
@ticki

ticki Nov 17, 2015

Contributor

Too me this is really noise. Rust's "everything is an expression" provides a really clean way of doing this namely if cond { a } else { b }.

Contributor

ticki commented Nov 17, 2015

Too me this is really noise. Rust's "everything is an expression" provides a really clean way of doing this namely if cond { a } else { b }.

@AngusP

This comment has been minimized.

Show comment
Hide comment
@AngusP

AngusP Nov 18, 2015

To me, the argument for it is the same as the argument for match - It's not necessary to have match for the language to be able to work, a match is a glorified/crazy if/else structure, but it looks nicer and is more understandable & concise, so it's in the language and everyone's happy with it. The ternary operator is the flip side of this, yes it is equivalent to some if/else based structure, usually a very simple one, but it adds code clarity if you can dispense with a large amount of syntax in favour of something much less messy.

/* Preferable, in my opinion, has just 2 characters of syntax */
let x = y > 3 ? 3 : 0;

/* messier imho, 10 characters of syntax*/
let x = if y > 3 { 3 } else { 0 };

To me the justification for this is the same as the justification for the following:

/* I'm sure we can all agree the match version here is better */
let x = match token {
        '+' => 4,
        '-' => 3,
        '*' => 2,
        '/' => 1,
        _ => 0
};

let x = if token == '+' {
        4
} else if token == '-' {
        3
} else if token == '*' {
        2
} else if token == '/' {
        1
} else {
        0
};

In fact with the ternary operator we can have nice* things like this concise case-like statement:

let x = y < 3  ? 3  :
        y < 10 ? 10 :
        y < 23 ? 11 :
        y < 42 ?  0 ;

(* Nice, in some people's opinion, and probably awful in other's.)

AngusP commented Nov 18, 2015

To me, the argument for it is the same as the argument for match - It's not necessary to have match for the language to be able to work, a match is a glorified/crazy if/else structure, but it looks nicer and is more understandable & concise, so it's in the language and everyone's happy with it. The ternary operator is the flip side of this, yes it is equivalent to some if/else based structure, usually a very simple one, but it adds code clarity if you can dispense with a large amount of syntax in favour of something much less messy.

/* Preferable, in my opinion, has just 2 characters of syntax */
let x = y > 3 ? 3 : 0;

/* messier imho, 10 characters of syntax*/
let x = if y > 3 { 3 } else { 0 };

To me the justification for this is the same as the justification for the following:

/* I'm sure we can all agree the match version here is better */
let x = match token {
        '+' => 4,
        '-' => 3,
        '*' => 2,
        '/' => 1,
        _ => 0
};

let x = if token == '+' {
        4
} else if token == '-' {
        3
} else if token == '*' {
        2
} else if token == '/' {
        1
} else {
        0
};

In fact with the ternary operator we can have nice* things like this concise case-like statement:

let x = y < 3  ? 3  :
        y < 10 ? 10 :
        y < 23 ? 11 :
        y < 42 ?  0 ;

(* Nice, in some people's opinion, and probably awful in other's.)

@niconii

This comment has been minimized.

Show comment
Hide comment
@niconii

niconii Nov 18, 2015

Member

👎

if ... else is more readable, and just looks nicer IMO. I don't agree that terser syntax implies better syntax in all cases.

Incidentally, note that match can do things an if ... else chain can't do, or cannot do easily:

fn main() {
    let mut my_option = Some(5);

    match my_option {
        // `ref mut x` creates a binding `x` which is a mutable
        // reference to the number inside `my_option`
        Some(ref mut x) => { *x = 10; },
        None => { }
    }

    // `my_option` is now `Some(10)`
    println!("{:?}", my_option);
}

So, I don't think the relationship between match and if ... else, and between if ... else and ?:, are very similar.

Member

niconii commented Nov 18, 2015

👎

if ... else is more readable, and just looks nicer IMO. I don't agree that terser syntax implies better syntax in all cases.

Incidentally, note that match can do things an if ... else chain can't do, or cannot do easily:

fn main() {
    let mut my_option = Some(5);

    match my_option {
        // `ref mut x` creates a binding `x` which is a mutable
        // reference to the number inside `my_option`
        Some(ref mut x) => { *x = 10; },
        None => { }
    }

    // `my_option` is now `Some(10)`
    println!("{:?}", my_option);
}

So, I don't think the relationship between match and if ... else, and between if ... else and ?:, are very similar.

@pnkfelix

This comment has been minimized.

Show comment
Hide comment
@pnkfelix

pnkfelix Nov 18, 2015

Member

@AngusP

It's not necessary to have match for the language to be able to work, a match is a glorified/crazy if/else structure,

I'm afraid you do not understand match. It is strictly more expressive than if / else.

Member

pnkfelix commented Nov 18, 2015

@AngusP

It's not necessary to have match for the language to be able to work, a match is a glorified/crazy if/else structure,

I'm afraid you do not understand match. It is strictly more expressive than if / else.

@AngusP

This comment has been minimized.

Show comment
Hide comment
@AngusP

AngusP Nov 18, 2015

@pnkfelix sorry yeah, I should have worded that better, I'm aware that pattern matching is strictly more expressive than ifs & else's, and that in rust if/else is treated as a special case of match.

If/else and match both exist because they aren't the same thing exactly, while ?: and if/else are the same thing. That however does not mean we should immediately dismiss it's value. Bearing in mind these are language choices not style choices we're trying to make.

AngusP commented Nov 18, 2015

@pnkfelix sorry yeah, I should have worded that better, I'm aware that pattern matching is strictly more expressive than ifs & else's, and that in rust if/else is treated as a special case of match.

If/else and match both exist because they aren't the same thing exactly, while ?: and if/else are the same thing. That however does not mean we should immediately dismiss it's value. Bearing in mind these are language choices not style choices we're trying to make.

@niconii

This comment has been minimized.

Show comment
Hide comment
@niconii

niconii Nov 18, 2015

Member

Something interesting; due to #803 and its expr: Type syntax being accepted, this may be in conflict with #243 (not yet accepted) due to it using expr? syntax as sugar for try!(expr).

fn bar(_x: bool) -> bool {
    false
}

fn foo() -> Result<fn() -> bool, bool> {
    let f = Ok(bar);
    let bool = true;

    // Interpretation 1: Err(try!(f)(bool): bool)
    // Interpretation 2: Err(if f { bool } else { bool })
    Err(f?(bool):bool)
}

fn main() {
    println!("{:?}", foo())
}

Now, it isn't completely ambiguous in this case (f isn't a bool after all, and thus interpretation 2 fails to compile), but the fact that it comes down to the type of f makes me wary.

Member

niconii commented Nov 18, 2015

Something interesting; due to #803 and its expr: Type syntax being accepted, this may be in conflict with #243 (not yet accepted) due to it using expr? syntax as sugar for try!(expr).

fn bar(_x: bool) -> bool {
    false
}

fn foo() -> Result<fn() -> bool, bool> {
    let f = Ok(bar);
    let bool = true;

    // Interpretation 1: Err(try!(f)(bool): bool)
    // Interpretation 2: Err(if f { bool } else { bool })
    Err(f?(bool):bool)
}

fn main() {
    println!("{:?}", foo())
}

Now, it isn't completely ambiguous in this case (f isn't a bool after all, and thus interpretation 2 fails to compile), but the fact that it comes down to the type of f makes me wary.

@withoutboats

This comment has been minimized.

Show comment
Hide comment
@withoutboats

withoutboats Nov 18, 2015

Contributor

@AngusP the argument you're looking for is not match but if let, which is purely syntactic sugar for a special case of match. But of course this is not a compelling argument in itself, just because the language has some sugar doesn't mean it has to adopt all sugars.

Some of the questions to evaluate regarding a proposed sugar are:

  • What is the benefit of this sugar to users? How much boilerplate is removed, how many characters less are typed, how does it reduce rightward drift?
  • How often would this sugar be used? Is this a common pattern?
  • How much more accessible is this sugar? Does it make code more readable, or make writing well-structured programs more at-hand?

I think that the reason a ternary particularly doesn't hold up to me is that while if cond { A } else { B } is more characters than cond ? A : B, it isn't any more boilerplate in terms of control paths represented. Compare that to the savings in if let PAT = EXPR { A } versus match EXPR { PAT => A, _ => () }, which has a whole unnecessary match arm.

I also don't think its actually that common of a pattern, because if itself is a less common pattern in Rust. I just grepped an ~5000 line codebase I'm working on for ifs appearing in the rvalue position, and found only 1, whereas I found 14 match statements in that position (there were 88 ifs and 96 matches overall).

Another problem getting this through I think is that the reason ternary exists in many languages is that they do not have if expressions. Not having a ternary serves as a distinction and a pedagogical function about Rust's expression-orientedness.

And finally there are the syntactic issues with using those symbols for ternary, which would necessitate some alternate proposal like => ,. So it wouldn't be any more familiar to people coming from other languages, but instead of introducing expression-orientedness it would just be a weird thing about Rust's ternary operator.

Contributor

withoutboats commented Nov 18, 2015

@AngusP the argument you're looking for is not match but if let, which is purely syntactic sugar for a special case of match. But of course this is not a compelling argument in itself, just because the language has some sugar doesn't mean it has to adopt all sugars.

Some of the questions to evaluate regarding a proposed sugar are:

  • What is the benefit of this sugar to users? How much boilerplate is removed, how many characters less are typed, how does it reduce rightward drift?
  • How often would this sugar be used? Is this a common pattern?
  • How much more accessible is this sugar? Does it make code more readable, or make writing well-structured programs more at-hand?

I think that the reason a ternary particularly doesn't hold up to me is that while if cond { A } else { B } is more characters than cond ? A : B, it isn't any more boilerplate in terms of control paths represented. Compare that to the savings in if let PAT = EXPR { A } versus match EXPR { PAT => A, _ => () }, which has a whole unnecessary match arm.

I also don't think its actually that common of a pattern, because if itself is a less common pattern in Rust. I just grepped an ~5000 line codebase I'm working on for ifs appearing in the rvalue position, and found only 1, whereas I found 14 match statements in that position (there were 88 ifs and 96 matches overall).

Another problem getting this through I think is that the reason ternary exists in many languages is that they do not have if expressions. Not having a ternary serves as a distinction and a pedagogical function about Rust's expression-orientedness.

And finally there are the syntactic issues with using those symbols for ternary, which would necessitate some alternate proposal like => ,. So it wouldn't be any more familiar to people coming from other languages, but instead of introducing expression-orientedness it would just be a weird thing about Rust's ternary operator.

@oli-obk

This comment has been minimized.

Show comment
Hide comment
@oli-obk

oli-obk Dec 1, 2015

Contributor

In fact with the ternary operator we can have nice* things like this concise case-like statement:

let x = y < 3  ? 3  :
        y < 10 ? 10 :
        y < 23 ? 11 :
        y < 42 ?  0 ;

It's not a good argument if your "nice" example doesn't compile. I assume you wanted to return something else in case y > 42 ? let's use 42

The rust version is much more clear imo, and it's visually harder to mess up match statements.

let x = match 4 {
    0...3 => 3,
    0...10 => 10,
    0...23 => 11,
    0...42 => 0,
    _ => 42,
};

IIRC we are getting ...N patterns, so the zero can go away, covering negative values, too.

Contributor

oli-obk commented Dec 1, 2015

In fact with the ternary operator we can have nice* things like this concise case-like statement:

let x = y < 3  ? 3  :
        y < 10 ? 10 :
        y < 23 ? 11 :
        y < 42 ?  0 ;

It's not a good argument if your "nice" example doesn't compile. I assume you wanted to return something else in case y > 42 ? let's use 42

The rust version is much more clear imo, and it's visually harder to mess up match statements.

let x = match 4 {
    0...3 => 3,
    0...10 => 10,
    0...23 => 11,
    0...42 => 0,
    _ => 42,
};

IIRC we are getting ...N patterns, so the zero can go away, covering negative values, too.

@steveklabnik

This comment has been minimized.

Show comment
Hide comment
@steveklabnik

steveklabnik Dec 1, 2015

Member

We explicitly removed the ternary long ago, due to the duplication with if. An RFC to add it back would have to come up with a significant justification, to override that big negative.

As such, I'm gonna give this one a close.

Member

steveklabnik commented Dec 1, 2015

We explicitly removed the ternary long ago, due to the duplication with if. An RFC to add it back would have to come up with a significant justification, to override that big negative.

As such, I'm gonna give this one a close.

@shelby3

This comment has been minimized.

Show comment
Hide comment
@shelby3

shelby3 May 2, 2016

I made a different point about contrast given a language with block indenting instead of brace-delimited blocks.

shelby3 commented May 2, 2016

I made a different point about contrast given a language with block indenting instead of brace-delimited blocks.

@AndrewBrinker

This comment has been minimized.

Show comment
Hide comment
@AndrewBrinker

AndrewBrinker May 2, 2016

How would a sans-brace syntax handle nested if-else, or multiple lines within what would have formerly been a brace-delimited block?

AndrewBrinker commented May 2, 2016

How would a sans-brace syntax handle nested if-else, or multiple lines within what would have formerly been a brace-delimited block?

@shelby3

This comment has been minimized.

Show comment
Hide comment
@shelby3

shelby3 May 3, 2016

How would a sans-brace syntax handle nested if-else, or multiple lines within what would have formerly been a brace-delimited block?

See how Python and Haskell handle it with indenting of the block.

Note in my idea, it is still possible to indent to continue an expression on the next line, without creating a nested block; and this is accomplished by indenting more than the exact number of (e.g. 2) spaces required to created a nested block. Also note that outdenting by exactly that same number (e.g. 2) spaces is required to end the block.

shelby3 commented May 3, 2016

How would a sans-brace syntax handle nested if-else, or multiple lines within what would have formerly been a brace-delimited block?

See how Python and Haskell handle it with indenting of the block.

Note in my idea, it is still possible to indent to continue an expression on the next line, without creating a nested block; and this is accomplished by indenting more than the exact number of (e.g. 2) spaces required to created a nested block. Also note that outdenting by exactly that same number (e.g. 2) spaces is required to end the block.

@shelby3

This comment has been minimized.

Show comment
Hide comment
@shelby3

shelby3 May 4, 2016

I concluded that for Rust's brace-delimited design, the absence of a ternary operator is the optimum design decision. For a block indenting language, the optimum appears to be to require : instead of else only in the single-line case and only allow it where it is in an expression that is assigned.

shelby3 commented May 4, 2016

I concluded that for Rust's brace-delimited design, the absence of a ternary operator is the optimum design decision. For a block indenting language, the optimum appears to be to require : instead of else only in the single-line case and only allow it where it is in an expression that is assigned.

@toomaj

This comment has been minimized.

Show comment
Hide comment
@toomaj

toomaj May 29, 2016

I'm very new to Rust, but I'm not new to programming. I believe it's not really necessary to have multiple ways of doing the same thing! specially when a clean readable version exits, in this case if-else.

toomaj commented May 29, 2016

I'm very new to Rust, but I'm not new to programming. I believe it's not really necessary to have multiple ways of doing the same thing! specially when a clean readable version exits, in this case if-else.

@danpantry

This comment has been minimized.

Show comment
Hide comment
@danpantry

danpantry Jun 6, 2016

My thoughts on this are that we don't need to make Rust any more terse than it already is 😄

danpantry commented Jun 6, 2016

My thoughts on this are that we don't need to make Rust any more terse than it already is 😄

@raingloom

This comment has been minimized.

Show comment
Hide comment
@raingloom

raingloom Aug 25, 2016

I, as a Rust noob also agree. I was a bit surprised when my ternary using code didn't work, but I'm actually glad I won't be tempted to use it.

raingloom commented Aug 25, 2016

I, as a Rust noob also agree. I was a bit surprised when my ternary using code didn't work, but I'm actually glad I won't be tempted to use it.

@ignitusboyone

This comment has been minimized.

Show comment
Hide comment
@ignitusboyone

ignitusboyone Sep 1, 2016

I see this is a pretty loaded request. I prefer ternary conditionals for chain loading case assignments. The syntax is perfectly readable once your taught the language structure. Personally if a langue doesn't support ternary it should at least support a postfix if.

if I can't have
return (value == 5) ? success : failure;
I would prefer
return success if (value == 5) else failure;
then
return if value == 5 { success } else { failure }.

ignitusboyone commented Sep 1, 2016

I see this is a pretty loaded request. I prefer ternary conditionals for chain loading case assignments. The syntax is perfectly readable once your taught the language structure. Personally if a langue doesn't support ternary it should at least support a postfix if.

if I can't have
return (value == 5) ? success : failure;
I would prefer
return success if (value == 5) else failure;
then
return if value == 5 { success } else { failure }.

@nyanzebra

This comment has been minimized.

Show comment
Hide comment
@nyanzebra

nyanzebra Dec 6, 2016

I had no idea that ternary operator was such a divisive topic... I am new to Rust, however, I find the arguments against ternary operator unrefined. The argument for not having ternary operator based on the clarity and existing functionality of the following :

let x = if (true) { 1i32 } else {2i32} 

is not that great of an argument to make. As it is easily understood in the form of

let x = true ? 1i32 : 2i32 

or perhaps in the form similar to match?

let x = true => 1i32, 2i32 

I think the discourse here is better served by determining what type of future Rust should have, whether a constrained Java like syntax or a free C/C++ syntax. Both of have merits and pitfalls. If Rust should be an expressive language for the developer, then implement ternary operator. If Rust should be a controlled language, then do not. Readability, in my opinion is a terrible argument... as I am sure I can make a terrible if else statement that would make you want to gouge your eyes out.

Maybe something like this is possible?

let x = if (true) { if (false) { true } else { false} } else { if (true) { false} else {true} }

nyanzebra commented Dec 6, 2016

I had no idea that ternary operator was such a divisive topic... I am new to Rust, however, I find the arguments against ternary operator unrefined. The argument for not having ternary operator based on the clarity and existing functionality of the following :

let x = if (true) { 1i32 } else {2i32} 

is not that great of an argument to make. As it is easily understood in the form of

let x = true ? 1i32 : 2i32 

or perhaps in the form similar to match?

let x = true => 1i32, 2i32 

I think the discourse here is better served by determining what type of future Rust should have, whether a constrained Java like syntax or a free C/C++ syntax. Both of have merits and pitfalls. If Rust should be an expressive language for the developer, then implement ternary operator. If Rust should be a controlled language, then do not. Readability, in my opinion is a terrible argument... as I am sure I can make a terrible if else statement that would make you want to gouge your eyes out.

Maybe something like this is possible?

let x = if (true) { if (false) { true } else { false} } else { if (true) { false} else {true} }
@oli-obk

This comment has been minimized.

Show comment
Hide comment
@oli-obk

oli-obk Dec 6, 2016

Contributor

@nyanzebra in Rust you can say if true { 1i32 } else { 2i32 }, so you save another pair of parens. Also, since we don't want any dangling-elseish code we'd need {} around the expressions and then we are back at rust's if/else notation.

Maybe something like this is possible?

In ternery notation that would be

let x = true ? false ? true : false : true ? false : true;

Which in my opinion is way worse than the if/else version

Also it should look like

let x = if true { if false { true } else { false } } else { if true { false } else { true } };

Which I'm fairly sure that clippy will tell you to turn into

let x = if true { !false } else { !true };

And then after another round of clippy:

let x = if true { true } else { false };

And after a third round

let x = true;

if you want to address multiple booleans you can always use a match:

match (a, b) {
    (true, true) => ...,
    (true, false) => ...,
    (false, true) => ...,
    (false, false) => ...,
}

Readability, in my opinion is a terrible argument...

The thing is. That horrendous if/else you showed, is be formatted by rustfmt to

    let x = if (true) {
        if (false) { true } else { false }
    } else {
        if (true) { false } else { true }
    };

Which is cleanly readable. I'm not even sure how to format the ternary operator in a readable way

/rant /sorry

Contributor

oli-obk commented Dec 6, 2016

@nyanzebra in Rust you can say if true { 1i32 } else { 2i32 }, so you save another pair of parens. Also, since we don't want any dangling-elseish code we'd need {} around the expressions and then we are back at rust's if/else notation.

Maybe something like this is possible?

In ternery notation that would be

let x = true ? false ? true : false : true ? false : true;

Which in my opinion is way worse than the if/else version

Also it should look like

let x = if true { if false { true } else { false } } else { if true { false } else { true } };

Which I'm fairly sure that clippy will tell you to turn into

let x = if true { !false } else { !true };

And then after another round of clippy:

let x = if true { true } else { false };

And after a third round

let x = true;

if you want to address multiple booleans you can always use a match:

match (a, b) {
    (true, true) => ...,
    (true, false) => ...,
    (false, true) => ...,
    (false, false) => ...,
}

Readability, in my opinion is a terrible argument...

The thing is. That horrendous if/else you showed, is be formatted by rustfmt to

    let x = if (true) {
        if (false) { true } else { false }
    } else {
        if (true) { false } else { true }
    };

Which is cleanly readable. I'm not even sure how to format the ternary operator in a readable way

/rant /sorry

@tolkanabroski

This comment has been minimized.

Show comment
Hide comment
@tolkanabroski

tolkanabroski May 9, 2017

5 minutes into rust first thing that i look up was Ternary operator. Im back to C. RIP.

tolkanabroski commented May 9, 2017

5 minutes into rust first thing that i look up was Ternary operator. Im back to C. RIP.

@oli-obk

This comment has been minimized.

Show comment
Hide comment
@oli-obk

oli-obk May 9, 2017

Contributor

You need to step up your trolling game significantly if you want to fence with the rust community. We've been hardened by the borrow checker, so these puny attempts just get tagged A-musing + wontfix

Contributor

oli-obk commented May 9, 2017

You need to step up your trolling game significantly if you want to fence with the rust community. We've been hardened by the borrow checker, so these puny attempts just get tagged A-musing + wontfix

@tolkanabroski

This comment has been minimized.

Show comment
Hide comment
@tolkanabroski

tolkanabroski May 9, 2017

No interest in trolling or community . Thank you. Bye.

tolkanabroski commented May 9, 2017

No interest in trolling or community . Thank you. Bye.

@danpantry

This comment has been minimized.

Show comment
Hide comment
@danpantry

danpantry May 9, 2017

if you're choosing your language based on the ternary operator I think you may have somewhat larger issues :)

danpantry commented May 9, 2017

if you're choosing your language based on the ternary operator I think you may have somewhat larger issues :)

@le-jzr

This comment has been minimized.

Show comment
Hide comment
@le-jzr

le-jzr May 9, 2017

"back to C" he said, loading his gun for another round of Russian roulette...

le-jzr commented May 9, 2017

"back to C" he said, loading his gun for another round of Russian roulette...

@BurntSushi

This comment has been minimized.

Show comment
Hide comment
@BurntSushi

BurntSushi May 9, 2017

Member

Really? Enough.

Member

BurntSushi commented May 9, 2017

Really? Enough.

@rust-lang rust-lang locked and limited conversation to collaborators May 9, 2017

@Centril Centril added the T-lang label Feb 23, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.