• Post Reply Bookmark Topic Watch Topic
  • New Topic

Ternary operator with if/elseif/else  RSS feed

 
Ed Carrington
Ranch Hand
Posts: 77
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can I use a ternary operator for the below?
I have used tenary operator in the past for if/else but not sure how to do it with if/elseif/else.
Please advise.
 
Jeanne Boyarsky
author & internet detective
Sheriff
Posts: 37256
519
Eclipse IDE Java VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ed,
You would have to use a nested ternary operator. This is really hard to read, so I recommend sticking with the if/elseif/else.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It can be done like this:

Personally I don't find that hard to read at all, but it does get funny looks from some people when they first see it. For a longer sequence, I'd like to be able to format it like this:

But I can't convince IntelliJ to do this; it keeps wanting to show nesting:

Or if I use "align when multiline":

Feh.

For comparison, the if / else if version of this could look like this:

But it's considered perfectly acceptable to format it like this instead:

Even among people who otherwise would insist that every if and else clause should have braces around it.

So why can't we do exactly the same thing with the ternary? I think it's both more readable and more compact than the if/else version of the code, and has the added benefit of throwing en error if the final "else", to assure that the variable has been assigned by at least one branch of the code. We just need to get more people familiar with this alternative, so they will stop giving me strange looks when I do it.
[ October 22, 2007: Message edited by: Jim Yingst ]
 
Ed Carrington
Ranch Hand
Posts: 77
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, excellent examples!
 
Jeanne Boyarsky
author & internet detective
Sheriff
Posts: 37256
519
Eclipse IDE Java VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim: Funny look .

Your longer version of the ternary example is quite readable. I've never seen it formatted like that before. In a good way. I have seen the one line version. And yes, I do find it hard to read. Mainly because I have to look in three different positions on the line to find the assignment values.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Jeanne]: Jim: Funny look .

Whachoo lookin' at?

Update: IntelliJ will format this acceptably if you use "align when multiline" and put the ':' on the end of the line:

I normally put binary operators at the start of a line, but I know many people put them at the end. I guess I can live with that.

Eclipse seems to have the same problems formatting this as IntelliJ above, except the problem doesn't seem to be fixed by putting the : at the end of a line. Still looks icky. Ah well.
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The only reason the ternary operator example is clearly readable is because the subject matter is immediately obvious, and fairly simple. Nested ternary operators is asking for trouble.

What do you gain from using the ternary operator?

I can tell you what you lose:

Break from standard convention
Even if it's not much less readable, it's still not AS readable.
I believe JVM 1.4 and 1.5 handle the ternary operator differently with autoboxing (I can't remember the example - someone fill me in? It was in Josh Bloch's puzzler book)
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Adam]: The only reason the ternary operator example is clearly readable is because the subject matter is immediately obvious, and fairly simple.

Yup - and simple things should be written simply. Chaining ternaries is pretty simple, and compact. No need to go on for many lines.

[Adam]: Nested ternary operators is asking for trouble.

Complex nesting requiring parens, maybe. Chains of ternaries are simple.

[Adam]: What do you gain from using the ternary operator?

I already pointed out the virtue of having it flag an error if you omit a final else, or otherwise fail to set a variable in one of the branches. Brevity is another. I dislike paging through a bunch of bloated code that does really simple things.

Comparators are another place where this style works well. From a previous discussion:

[Adam]: I can tell you what you lose:

Break from standard convention


This I agree with. The fact that it's nonstandard is the best reason not to do this. Essentially I'm arguing that it should be standard. But it's true, it isn't currently standard.

[Adam]: Even if it's not much less readable, it's still not AS readable.

I don't agree here. I find it more readable. Readability is often subjective though.

[Adam]: I believe JVM 1.4 and 1.5 handle the ternary operator differently with autoboxing (I can't remember the example - someone fill me in? It was in Josh Bloch's puzzler book)

I checked autoboxing and ternary in the index, and I don't see a puzzler that combines them. It's probably there, but I can't find it. Would be interested to hear what this refers to.
[ October 24, 2007: Message edited by: Jim Yingst ]
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It was something to do with null assignment and boxing, I really can't remember - and it's a minor thing because it's an obscure corner case - I'll try to find it and post it.

Readability is based upon perspective, and you've made good arguments for the limited use of the ternary operator - which may be as readable as the standard if/elseif/else structure. My argument that it's less readable is based upon the irregular use in most systems. This makes it less familiar, and thus less readable.

Taking a ternary example, and an if/elseif/else control out of context and examining them exclusively is the wrong test - reading through a method, and understanding how the flow changes based upon these structures is the test.

This conversation is good, though - I personally don't have any problem with the ternary style. I generally avoid it due to extremely varied levels of understanding across development teams.
[ October 24, 2007: Message edited by: Adam Schaible ]
 
Anand Hariharan
Rancher
Posts: 272
C++ Debian VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jim -

Originally posted by Jim Yingst:
[Adam]: The only reason the ternary operator example is clearly readable is because the subject matter is immediately obvious, and fairly simple.

Yup - and simple things should be written simply. Chaining ternaries is pretty simple, and compact. No need to go on for many lines.

[Adam]: Nested ternary operators is asking for trouble.

Complex nesting requiring parens, maybe. Chains of ternaries are simple.

[Adam]: What do you gain from using the ternary operator?

I already pointed out the virtue of having it flag an error if you omit a final else, or otherwise fail to set a variable in one of the branches. Brevity is another. I dislike paging through a bunch of bloated code that does really simple things.


I agree with everything you wrote so far. Specifically, your example in the other post (where you discussed how IntelliJ formats your chain of ternaries) is very nice.

However, the example ...

Originally posted by Jim Yingst:

Comparators are another place where this style works well. From a previous discussion:



... the intent of the code is obvious only because you formatted it that way. As such it takes advantage of operator precedence, and I would take several seconds to parse such an expression while reading through some code.

Note that in your previous example, you parenthesized the comparisons, thereby making it less dependent upon the way it is formatted. Besides, am sure you have seen code that is formatted (by the programmer) in one way, but it would not be the way the compiler would see it.

Originally posted by Jim Yingst:

[Adam]: I can tell you what you lose:

Break from standard convention


This I agree with. The fact that it's nonstandard is the best reason not to do this. Essentially I'm arguing that it should be standard. But it's true, it isn't currently standard.

[Adam]: Even if it's not much less readable, it's still not AS readable.

I don't agree here. I find it more readable. Readability is often subjective though.



Couldn't possibly disagree with anything there.

sincerely,
- Anand
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Anand]: ... the intent of the code is obvious only because you formatted it that way.

Well, sure. Lots of code is clear only because of good formatting. An if statement becomes hard to read if we don't indent the statements correctly - but that doesn't mean we shouldn't use if statements, does it?

I did forget to add the parentheses when I copied that last example from the old thread. I did more all the ? and : to the ends of lines rather than beginnings, as IntelliiJ likes. The parens aren't necessary, but they do add familiarity for readers, since we're used to seeing conditionals in if statements where parentheses around the conditional are required. So sure, let's add them:
 
Anand Hariharan
Rancher
Posts: 272
C++ Debian VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
[Anand]: ... the intent of the code is obvious only because you formatted it that way.

Well, sure. Lots of code is clear only because of good formatting. An if statement becomes hard to read if we don't indent the statements correctly - but that doesn't mean we shouldn't use if statements, does it?


Not sure what brought on the "... - but that doesn't mean we shouldn't use if statements, does it?". I certainly wasn't suggesting that.

In essence my points were -
  • Writing code that takes advantage of operator precedence is generally not a good idea. (I'll admit that it does have something to do with the subjective issue of readability.)
  • Such code is potentially dangerous when a programmer gets the precedence rules wrong, and formats code that is consistent with his/her wrong assumptions. Now not only is the code readable (because of the formatting), but it gives the reader of the code a WRONG idea of the code's intention. I'd rather see inscrutable code (because I will throw it away and rewrite my own) than see code that is readable but turns out to do the wrong thing. (Of course, I was not suggesting your code was wrong.)


  • In this light, I hope my sentence "... the intent of the code is obvious only because you formatted it that way." makes for a meaning that is different from avoiding use of ternary operators or if statement.

    An example contrived from my own experience in production code:



    Of course, this example has nothing to do with operator precedence. It has everything to do, however, with formatted code giving the WRONG impression to the reader.


    I did forget to add the parentheses when I copied that last example from the old thread.


    What thread is that? Your link in your previous post, points to this (currently ongoing) thread.

    best,
    - Anand
     
    Jim Yingst
    Wanderer
    Sheriff
    Posts: 18671
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    [Anand]: Not sure what brought on the "... - but that doesn't mean we shouldn't use if statements, does it?". I certainly wasn't suggesting that.

    I didn't think you were suggesting we shouldn't use ifs, but I thought maybe you were suggesting we should avoid nested / chained ternaries for this reason. So I was using if statements as a counterexample. But it sounds like I misunderstood your intent, so never mind.

    I certainly agree that bad formatting can give the wrong impression on a reader, and thus it's important to use formatting that does not mislead in this way.

    [Anand]: Such code is potentially dangerous when a programmer gets the precedence rules wrong

    Yeah, and that's why I'm happy to add the parens around the condition, to make that clearer. It was clear to me without the parens, but if others find it clearer with them, that's fine. However I tend to avoid having parens everywhere that I could because I find that too many nested parens start to become visually distracting. If I see blocks of three or four parens in a row and have to start counting them, that's probably too complex, IMO, so I look for other ways to format it. As a result I'm probably less likely to insert optional parens than many other programmers are.

    [Anand]: What thread is that? Your link in your previous post, points to this (currently ongoing) thread.

    Oops! I've fixed the link above. I meant this thread. Though there's also a similar discussion here. Thanks for catching that.
     
    Anand Hariharan
    Rancher
    Posts: 272
    C++ Debian VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Jim Yingst:
    However I tend to avoid having parens everywhere that I could because I find that too many nested parens start to become visually distracting. If I see blocks of three or four parens in a row and have to start counting them, that's probably too complex ...


    I agree. That's why I said it is "... generally not a good idea." It would be silly to re-write an expression such as -

    - using parens just to religiously adhere to "don't write code that takes advantage of operator precedence".

    Incidentally, my reason for insisting parens for sub-expressions within a ternary comes from a note in Stroustrup's "The C++ Programming Language". He provides an operator precedence table only to follow it up saying that the table should only be used as a guideline, because the language officially does not have operator precedence! He then provides an expression as an example that is impossible to parse using operator precedence, and how only by resorting to grammar, can one explain what that expression does.

    I suppose Java has tightened some of the grammar weaknesses? For example, will this (i.e., an equivalent) compile in Java? I know it will not in C++:



    I had raised this question up in the Usenet, and it elicited some very insightful responses.

    - Anand
     
    Jim Yingst
    Wanderer
    Sheriff
    Posts: 18671
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    [Anand]: Incidentally, my reason for insisting parens for sub-expressions within a ternary comes from a note in Stroustrup's "The C++ Programming Language". He provides an operator precedence table only to follow it up saying that the table should only be used as a guideline, because the language officially does not have operator precedence! He then provides an expression as an example that is impossible to parse using operator precedence, and how only by resorting to grammar, can one explain what that expression does.

    For comparison, the Java spec doesn't give a table of precedence or associativity rules at all - it just provides a grammar. Association and precedence can be inferred from that, but they're not part of the spec. The tutorial gives a table of precedence, but the spec does not.

    [Anand]: For example, will this (i.e., an equivalent) compile in Java?

    Yes, the Java equivalent of that would be:

    This did not compile under JDK 1.4 or earlier, but does compile as of JDK 5 and later. They rewrote the relevant section of the specification to incorporate generics, and along the way incidentally generalized the rules to be a bit more permissive here. The original rule was that between the second and third arguments of the conditional operator, if they were both reference types, one had to be assignable to the other. Meaning one had to be a subtype of (or same type as) the other. In JDK 5 and later, the rule instead allows pretty much anything for the second and third operators, and the overall type of the conditional expression is the least upper bound of the second and third arguments. That is, it's the most specific type which is still a supertype of the second and third arguments. If nothing else, it can be the Object class. Except they don't come out and say that very clearly; it's rather obfuscated. Oh well.
     
    Ilja Preuss
    author
    Sheriff
    Posts: 14112
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    What I like about the (chained) ternary operator is that it very clearly communicates that it's calculating *exactly* one value, for exactly one purpose (assigning it to a variable, returning it, whatever).

    That's something an if-else-chain doesn't communicate - you have to look very carefully to be sure.
     
    Anand Hariharan
    Rancher
    Posts: 272
    C++ Debian VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Originally posted by Jim Yingst:


    This did not compile under JDK 1.4 or earlier, but does compile as of JDK 5 and later. They rewrote the relevant section of the specification to incorporate generics, and along the way incidentally generalized the rules to be a bit more permissive here. The original rule was that between the second and third arguments of the conditional operator, if they were both reference types, one had to be assignable to the other. Meaning one had to be a subtype of (or same type as) the other. In JDK 5 and later, the rule instead allows pretty much anything for the second and third operators, and the overall type of the conditional expression is the least upper bound of the second and third arguments. That is, it's the most specific type which is still a supertype of the second and third arguments. If nothing else, it can be the Object class. Except they don't come out and say that very clearly; it's rather obfuscated. Oh well.


    Jim - Thank you for your insights.

    sincerely,
    - Anand
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!