-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Comments
Rust already has this: |
@dscorbett That does not look very nice |
I have been very happy with our if-expression syntax. Not everyone loves the ternary- |
-1. |
(Downgrading so-called "importance") |
I continue to be against ever adding the ternary. |
👎 We have |
Sorry, but 👎 from me too. I sympathise with the argument for terseness, but would rather we not duplicate the functionality of |
Rust tries to avoid having multiple ways to do the same thing. Furthermore, the |
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. |
👎 I think if..else is more readable than dedicated ternary symbols |
👎 EDIT: Sorry, I don't usually like being so terse, so let me just expand a touch. We have |
see also rust-lang/rust#1698 rust-lang/rust#1705 |
I am grateful that this was removed, so 👎 |
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; |
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. |
Systems programmer should be very familiar with Rust already has a lot of choices; you can specify types, or let the compiler infer them. |
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. |
You certainly can have multiple expressions. int main() {
int x;
return 1>0 ? ({ x=1; x; }): 2;
} |
(That's a GNU extension.) |
@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 |
It is not particularly sustainable to support the union of all functionality that anyone has ever wanted. |
I don't think any new syntax should be added under the justification of "why not." |
Too me this is really noise. Rust's "everything is an expression" provides a really clean way of doing this namely |
To me, the argument for it is the same as the argument for /* 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.) |
👎
Incidentally, note that 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 |
I'm afraid you do not understand |
@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. |
Something interesting; due to #803 and its 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 ( |
@AngusP the argument you're looking for is not Some of the questions to evaluate regarding a proposed sugar are:
I think that the reason a ternary particularly doesn't hold up to me is that while I also don't think its actually that common of a pattern, because 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 |
It's not a good argument if your "nice" example doesn't compile. I assume you wanted to return something else in case 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 |
We explicitly removed the ternary long ago, due to the duplication with As such, I'm gonna give this one a close. |
I made a different point about contrast given a language with block indenting instead of brace-delimited blocks. |
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. |
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 |
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 |
My thoughts on this are that we don't need to make Rust any more terse than it already is 😄 |
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. |
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 |
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 in Rust you can say
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) => ...,
}
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 |
5 minutes into rust first thing that i look up was Ternary operator. Im back to C. RIP. |
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 |
No interest in trolling or community . Thank you. Bye. |
if you're choosing your language based on the ternary operator I think you may have somewhat larger issues :) |
"back to C" he said, loading his gun for another round of Russian roulette... |
Really? Enough. |
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
The text was updated successfully, but these errors were encountered: