views:

505

answers:

5

Ahh, don't you just love a good ternary abuse? :) Consider the following expression:

true ? true : true ? false : false

For those of you who are now utterly perplexed, I can tell you that this evaluates to true. In other words, it's equivalent to this:

true ? true : (true ? false : false)

But is this reliable? Can I be certain that under some circumstances it won't come to this:

(true ? true : true) ? false : false

Some might say - well, just add parenthesis then or don't use it altogether - after all, it's a well known fact that ternary operators are evil!

Sure they are, but there are some circumstances when they actually make sense. For the curious ones - I'm wring code that compares two objects by a series of properties. It would be pretty nice if I cold write it like this:

obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4)

Clear and concise. But it does depend on the ternary operator associativity working like in the first case. Parenthesis would just make spaghetti out of it.

So - is this specified anywhere? I couldn't find it.

+15  A: 

Yes, you can rely on this (not only in C# but in all (that I know) other languages with a conditional operator) and your use-case is actually a pretty common practice although some people abhor it.

The relevant section in ECMA-334 (the C# standard) is 14.13 §3:

The conditional operator is right-associative, meaning that operations are grouped from right to left. [Example: An expression of the form a ? b : c ? d : e is evaluated as a ? b : (c ? d : e). end example]

Konrad Rudolph
A note on readability. Anyone with a functional programming background will immediately recognize this (it looks almost precisely like Haskell’s guard clauses with appropriate formatting). So while it might not be universally acceptable and usable, it certainly *is* idiomatic in certain circles and may be very appropriate in some projects. On a more personal note, *I* use it in personal projects, I find it *vastly* more readable than chained `if`s, and if you can’t read it then get out of my code.
Konrad Rudolph
"in certain circles [or projects]" is key!
Roger Pate
+14  A: 
Roger Pate
It's for a lambda expression. Other ways would be only marginally better IMHO.
Vilx-
Absolutely agreed. If you have to ask, then it's not clear. If it's not clear, then put f-ing parentheses around it and stop being a clever programmer. That's where the worst bugs come from.
gmagana
+1 for two valid points.
OregonGhost
I disagree that it is a good approach. It's not idiomatic and someone who has not encountered it needs to examine it closely to see what's going on. A series of if/then clauses is clearer.
mquander
yes, Anything I'M not familiar with, (or are too stuck in my ways to learn), must be 'clever' programming... –
Charles Bretana
Well... it's a fair point, of course. Would comments help? :) As I said, the reason for this is because I'm writing this in a lambda expression, so I'd like to keep it short, resembling a formula more than a piece of code.
Vilx-
Vilx: Why comments instead of parentheses? Which way is more obvious and least likely to result in docs/comments differing from code?
Roger Pate
Try to write the whole thing WITH parentheses. Personally, I'd prefer the row of IF statements then. It's more verbose, but at least cleaner.
Vilx-
Charles: What do you have to judge by, except yourself? It's a fair assumption that if he had a hard time deciphering the code (and I use 'decipher' intentionally), then anyone else *working on his project* will too.
Roger Pate
@Roger, no it's not a fair assumption. When I look at Lisp code I have no clue what it means. That doesn't mean it's bad code. Just cause someone doesn't like ternary operators, doesn't use them, and is therefore unfamiliar with reading them, doesn't mean they are unreadable... The same thing applies to lambdas the first few times I looked at them ... It's ok if someone doesn't want to use them, I can't (and wouldn't) try to force anyone to use anything they're uncomfortable with. Just don't disparage a tool because you don't like it and/or are not fluent or competent in it's use.
Charles Bretana
Do you often work on Lisp projects when you have no knowledge of Lisp?
Roger Pate
@Roger, how is that relevant? The point is that it's not readable because I'm not familiar or competent with it, not because it's bad code. The same is true for C/C# code which uses new features, like Generics/anonymous methods in C#2.x, or Lambdas in 3.x, until I take the time to learn them, and use them sufficiently to become fluent with them.
Charles Bretana
Following the conventions common in a project is how you maintain consistency, which improves readability. It would be a fool's errand to think you can write code readable to everyone---including those who don't even know the language! But maintaining consistency within a project is a useful goal. When you break a project's accepted conventions you lead to debate that detracts from solving the real goal. Just look at all the effort spent on this question, versus how long it would take to add parentheses and move on.
Roger Pate
FWIW, I made a conscious decision not to learn the C operator precedence table, on the principal that if I had to learn the table to parse my expressions it would confuse other people (and maybe me, later on). If it isn't obvious, I parenthesize it.
David Thornley
So, what constitutes readable, or unreadable, good, or bad, code is dependant on an individual teams' consistency standards, and not on the code itself? I guess you're free to define anything anyway you want, but that's not how I would define a quality attribute. to me, the definition has to be such that it is dependant on characteristics internal to whatever is being evaluated, not on external factors which can differ from one setting to another.
Charles Bretana
In this forum we are not on a single team, with a single standard. SO making statements which purport to judge qualities like readability, or clarity, when your personal definition is dependant on an internal standard which others here may or may not subscribe to or use, would be .... not as clear ???
Charles Bretana
Charles: It depends on context, of course. How anything is measured depends on the requirements, and those are different for software making my coffee, controlling the space shuttle, or doing my taxes. We are not on a single team, but I can deduce it is neither common nor accepted *for his project* **because** he had to ask.
Roger Pate
@Roger, well, his question was about the precedence order, and, contray to your statement about his feelings, to quote him " It would be pretty nice if I cold write it like this: ,<snip> Clear and concise!" That tells me just the opposite of what you are saying. He would prefer to use the ternary! But this is still not relevant to my point which is that software quality be it readability, or clarity, or whatever, does not, should not, depend on subjective judgments. If he said If Else clauses are evil, does that make them so? Of course not, no matter if his team treats them as anathema.
Charles Bretana
If his project had a specific convention not to use else clauses, then he should either 1) not use else clauses, or 2) get that convention changed before using else clauses. This is assuming that he wants to solve the problem his project set out to solve---if he just wants to spend all day arguing with other team members, then he should do as you say. We will just have to disagree, because no matter how *you* judge code, doesn't necessarily make *your criteria* right for any other project.
Roger Pate
"if he just wants to spend all day arguing with other team members, then he should do as you say.." ???? your chutzpa is astounding... You just assume that your judgment is universal and that anyone who disagrees is just a argumentative iconoclast ? Then you clearly miss my point totally, and after making several attempts now to communicate it, I guess we will have to agree to stop communicating... (I can't say agree to disagree, cause frankly, I have no sense from you that you have any idea what it is I disagree with you about... )
Charles Bretana
+1  A: 

Refer to msdn: http://msdn.microsoft.com/en-us/library/ty67wk28%28VS.80%29.aspx

"If condition is true, first expression is evaluated and becomes the result; if false, the second expression is evaluated and becomes the result. Only one of two expressions is ever evaluated."

dcp
True, but this doesn't say anything about associativity.
Vilx-
+2  A: 

It's described here

yu_sha
+4  A: 

The assertion that parentheses detract from the readability of the code is a false assumption. I find the parenthetical expression much more clear. Personally, I would use the parentheses and/or reformat over several lines to improve readability. Reformatting over several lines and using indenting can even obviate the need for parentheses. And, yes, you can rely on the fact that the order of association is deterministic, right to left. This allows the expression to evaluate left to right in the expected fashion.

obj1.Prop1 != obj2.Prop1
     ? obj1.Prop1.CompareTo(obj2.Prop1)
     : obj1.Prop2 != obj2.Prop2
           ? obj1.Prop2.CompareTo(obj2.Prop2)
           : obj1.Prop3 != obj2.Prop3
                  ? obj1.Prop3.CompareTo(obj2.Prop3)
                  : obj1.Prop4.CompareTo(obj2.Prop4);
tvanfosson
Re: your last sentence. I note that the question wasn't about order of evaluation, it was about associativity. Those two things are completely different.
Eric Lippert
I should have been more clear that it associates in a way that allows the expression to be evaluated left to right in the expected fashion.
tvanfosson