Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

For example, would you prefer this one-liner

int median(int a, int b, int c) {
    return (a<b) ? (b<c) ? b : (a<c) ? c : a : (a<c) ? a : (b<c) ? c : b;
}

or an if/else solution involving multiple return statements?

When is ?: appropriate, and when is it not? Should it be taught to or hidden from beginners?

share|improve this question

closed as not constructive by gnat, Walter, Thomas Owens Nov 26 '12 at 16:39

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.If this question can be reworded to fit the rules in the help center, please edit the question.

209  
This particular use of it is :) –  karmajunkie Dec 20 '10 at 16:48
19  
I prefer questions like this to end with "considered harmful?" rather than "evil?" It's sort of a time-honored tradition in programming. –  Jesse C. Slicer Dec 20 '10 at 19:13
3  
Post the if/else solution and see the difference and judge for your self –  OscarRyz Dec 20 '10 at 19:30
5  
Who coded that, and what does their version of a median for four numbers look like? Or five? –  Mason Wheeler Dec 20 '10 at 21:56
5  
I will summon Paracelso and his "Nothing is poision and everything is poison, the difference is in the dose" here. Your example is a perfect case of a poisonous dose. –  Konamiman Nov 26 '12 at 8:50

32 Answers 32

up vote 199 down vote accepted

Is the ternary operator evil?

No it's a blessing.

When is ?: appropriate?

When it's something so simple you don't want to waste many lines for.

and when is it not?

When the readability and clearness of code suffers and a potential for a mistake through insufficient attention increases, for example, with many chained operators, just like in your example.


The litmus test is when you begin to doubt your code is easily readable and maintainable in the long run. Then don't do it.

share|improve this answer
17  
+1 for When the readability and clearness of code suffers. With many chained operators, just like in your example. The example takes longer to understand than equivalent if/else's. –  sange Dec 20 '10 at 16:44
19  
+1 bravo for the great explanation! Developers don't tend to realise that some things are judgement calls, they want everything to be black and white. It drives me nuts. I've encountered to many people of the opinion "X is evil, lets never use it.". I prefer "X is great if you use it for what it's good at". –  Doctor Jones Dec 20 '10 at 16:48
47  
It is also evil if it's used: myVar = (someExpression) ? true : false; Aaaaarrgh! –  adamk Dec 20 '10 at 17:55
15  
@adamk: Try this for evil: myVar = someExpression ? false : true; –  Dean Harding Dec 20 '10 at 22:00
6  
How about (someExpression ? var1 : var2)++ :-) –  FredOverflow Dec 21 '10 at 10:42

Biggest win: Showing that there is a single target of action.

if ( $is_whatever )
    $foo = 'A';
else
    $foo = 'B';

There are two code paths that you can follow, and the reader must read carefully to see which two variables are being set. In this case, it's only one variable, but the reader has more to read to figure that out. After all, it could have been this:

if ( $is_whatever )
    $foo = 'A';
else
    $bar = 'B';

With the ternary operator, it's clear that only one variable is being set.

$foo = $is_whatever ? 'A' : 'B';

At the very lowest level, it is the DRY (Don't Repeat Yourself) principle at its most basic. If you can specify $foo only once, do so.

share|improve this answer

One difference that (I think) no-one has pointed out is that if-else can't return a value, whereas the ternary operator can.

Coming from F#, I sometimes like to use the ternary operator to mimic pattern matching.

match val with
| A -> 1
| B -> 3
| _ -> 0

vs

return val == A ? 1 : 
       val == B ? 3 : 
       0;
share|improve this answer
3  
Also useful in C and C++ for initializing const variables that can't be changed later. –  David Thornley Jan 25 '11 at 19:53
1  
+1 for a very reasonable, readable use. –  Scott Whitlock Jan 25 '11 at 20:27

It's also necessary for const

const int nLegs  = isChicken ? 2: 4 ;
share|improve this answer

A shop that regularly writes 600-1200-line methods should not tell me that a ternary is "hard to understand". Any shop that regularly allows five conditions to evaluate a code branch should not tell me that concretely summarized conditions in a ternary are "hard to read".

share|improve this answer

Evil? Look, they're just different.

if is a statement. (test ? a : b) is an expression. They're not the same thing.

Expressions exist to express values. Statements exist to perform actions. Expressions can appear inside statements, but not vice-versa. So you can use ternary expressions within other expressions, like for terms in a summation, or for arguments to a method, and so on. You don't have to, but you can if you want to. There's nothing wrong with that. Some people might say that's evil, but that's their opinion.

One value of a ternary expression is it makes you to handle both true and false cases. if statements don't.

If you're worried about readability, you can format them readably.

Somehow "evil" crept into the programming vocabulary. I'd love to know who first dropped it. (Actually, I have a suspect - he's at MIT.) I would rather we had objective reasons for value judgements in this field, not just peoples' taste and name-calling.

share|improve this answer
1  
May I have a hint on who the suspect is? Just to improve my knowledge of the field a bit. –  mlvljr Jan 26 '11 at 10:52
1  
@mlvljr: Well I could be wrong, so better not to. –  Mike Dunlavey Jan 26 '11 at 16:52

In your example:

def median(a, b, c):
    if a < b < c: return b
    if a < c < b: return c
    if b < a < c: return a
    if b < c < a: return c
    if c < a < b: return a
    if c < b < a: return b

is very simple to read, and obvious. The variable between the < < is the return value.

Update

same, but fewer lines of code. Still simple I think.

def median(a, b, c):
    if b<a<c or c<a<b: return a
    if a<b<c or c<b<a: return b
    if a<c<b or b<c<a: return c
share|improve this answer
1  
Perhaps, but it's legible. –  Christopher Mahan Jan 25 '11 at 21:29

Here's an example of when it is evil:

oldValue = newValue >= 0 ? newValue : oldValue;

It's confusing and wasteful. The compiler could optimize out the second expression (oldValue = oldValue), but why did the coder do this in the first place?

Another doozy:

thingie = otherThingie != null ? otherThingie : null;

Some people are just not meant to be coders...

Greg says that the equivalent if statement is 'noisy'. It is if you write it noisily. But that same if can be written as:

if ('a' == $s) return 1;
if ('b' == $s) return 2;
if ('c' == $s) return 3;
return 4;

Which is no noisier than the ternary. I wonder if the ternary short-cuts; do all of the expressions get evaluated?

share|improve this answer

IMO, the operator itself isn't evil, but the syntax used for it in C (and C++) is excessively terse. IMO, Algol 60 did it better, so something like this:

A = x == y ? B : C;

would look more like this (but sticking to C-like syntax in general):

A = if (x==y) B else C;

Even with that, excessively deep nesting can lead to problems with readability, but at least A) anybody who's done programming at all can figure it out a simple one, and B) people who understand it can handle considerably deeper nesting pretty easily. OTOH, I'd also note that in LISP (for example) a cond is pretty much like a ternary statement -- not a set of statements, but a single expression the yields a value (then again, most of LISP is like that...)

share|improve this answer

That particular expression makes my eyes hurt; I'd lash out an any developer on my team that used it because it's unmaintainable.

Ternary operators are not evil when used well. They don't even have to be single lines; A long one that is formatted well can be very clear and easy to understand:

return
      ( 'a' == $s ) ? 1
    : ( 'b' == $s ) ? 2
    : ( 'c' == $s ) ? 3
    :                 4;

I like that better than the equivalent if/then/else chain:

if ( 'a' == $s ) {
    $retval = 1;
}
elsif ( 'b' == $s ) {
    $retval = 2;
}
elsif ( 'c' == $s ) {
    $retval = 3;
}
else {
    $retval = 4;
}

return $retval;

I'll reformat those into:

if    ( 'a' == $s ) { $retval = 1; }
elsif ( 'b' == $s ) { $retval = 2; }
elsif ( 'c' == $s ) { $retval = 3; }
else                { $retval = 4; }

return $retval;

if the conditions and assignments allow easy alignment. Still I prefer the ternary version because it's shorter and doesn't have as much noise around the conditions and assignments.

share|improve this answer
  1. "Evil" arguments aside, in my experience I've found a high correlation between a programmer's use the ternary operator and the likelihood of his or her entire codebase being difficult to read, follow, and maintain (if not outright undocumented). If a programmer's more concerned with saving a few 1-2 character lines than someone being able to understand his or her code, then any minor confusion understanding a ternary statement is usually the tip of the iceberg.

  2. Ternary operators attract magic numbers like s**t attracts flies.

If I was looking for an Open Source library to solve a particular problem, and I saw code such as the original poster's ternary operators in a candidate for said library, warning bells would start going off in my head and I'd start considering moving on to some other project to borrow from.

share|improve this answer

I think the unnested ternary operator (i.e., a statement where it's used only once) is fine, but if you're nesting more than one, it becomes somewhat hard to read.

share|improve this answer
3  
This might be considered an oversimplification, but it's a very easy guideline to follow and it works in most cases. –  Alan Pearce Dec 21 '10 at 15:08

Can I say it? I can't manage to find this particular application of the ternary operation evil:

  1. the operation it performs is pretty trivial, and once you went trough it once it's hardly possible some bugs will come out;
  2. what it does is clearly stated in the function name;
  3. taking >1 line for something so obvious and that so clearly wouldn't be improved in the future (unless a magic median algorithm has lived undetected until now).

Please have mercy, my reputation is pretty pitiful already.

share|improve this answer

Absolutely not evil. In fact, it's pure, and if-then-else isn't.

In functional languages like Haskell, F#, ML etc., it's the if-then-else statements that are considered evil.

The reason for this is that any "action" like an imperative if-then-else statement requires you to separate a variable declaration from its definition, and introduces state to your function.

For instance, in the following code:

const var x = n % 3 == 1
    ? Parity.Even
    : Parity.Odd;

vs.

Parity x;
if (n % 3 == 1)
    x = Parity.Even;
else
    x = Parity.Odd;

The first one has two advantages aside from being shorter:

  1. x is a constant, and so offers much fewer chance of introducing bugs, and can potentially be optimized in ways the second could never be.
  2. The type is made clear by the expression, so the compiler can effortlessly infer that x needs to be of type Parity.

Confusingly, in functional languages, the ternary operator is often called if-then-else. In Haskell, you might say x = if n mod 3 == 1 then Odd else Even.

share|improve this answer

When is ?: appropriate, and when is it not?

  • If you don't get a performance gains don’t use it since it affects the readability of your code.
  • Use it ones, and don’t nest it.
  • It’s harder to debug.

Should it be taught to or hidden from beginners?

Doesn't matter, it's not too complex for a “beginner” to learn.

share|improve this answer

While nesting ternary operator, liberal use of parentheses along with some indentation will serve the dual purpose of smaller code and enhanced legibility than a code with too many if/else.

share|improve this answer

Far from being evil, the ternary operator is a godsend.

  • It is most useful when you want to make a decision in a nested expression. The classic example is a function call:

    printf("I see %d evil construct%s in this program\n", n, n == 1 ? "" : "s");
    
  • In your particular example, the ternary is nearly gratuitous, since it is the top-level expression under a return. You can lift the conditional out to the statement level without duplicating anything other than the return keyword.

N.B. Nothing will ever make that particular algorithm for median easy to read.

share|improve this answer

Wow! Whoever wrote this is either trying to compensate for something or is just plain evil. Was this an entry in some kind of obfuscated code contest?

As everyone else has already said code should be readable and people shouldn't have to reconstruct parts of the compiler in order to understand what a line of code is doing.

share|improve this answer

As others said, its a blessing, but I always use parenthesis to read expressions easier:

a = (x == y)?(
  (a>0)?(
    a-1
  ):(b)
):(
  (b<0)?(
    b+1
  ):(a)
);
share|improve this answer

Anything that makes your code uglier is evil.

If you use ternary to make your code cleaner then sure use it. Sometimes in like php it's great to do inline substitutions, e.g.

"Hello ".($Male?"Mr":"Ms")." $Name

That saves a few lines, and it pretty clear, but your example needs at least better formatting to be clear, and ternary isn't really good for multi-line, then you might as well use if/else.

share|improve this answer

When is appropriate, and when is it not?

I think that when developing for a homogeneous group of people, there is no problem but when you have to deal with people that handle different levels, this kind of oneliners only introduce a further level of complexyti to the code. So, my policy on the matter is: code clear and dont explain rather than code short and explain 123123 times.

Should it be taught to or hidden from beginners?

I should not be taught to beginners, rather prefert them to figure it out when need emerges, so it'll be used only when necesary and not every time you need an if.

share|improve this answer

This can be reformatted to be as nice-looking as the if/else combination:

int median(int a, int b, int c)
{
    return
        (a<b)
        ?
            (b<c)
            ? b
            :
                (a<c)
                ? c
                : a
        :
            (a<c)
            ? a
            :
                (b<c)
                ? c
                : b;
}

But the problem is that I am not really sure if I got the indentation right to represent what will actually happen. :-)

share|improve this answer
3  
+1 I think this is far better than an equivalent if-else structure. The key is the formatting. –  Orbling Dec 20 '10 at 22:13
11  
If I saw this in a code base, I would seriously consider looking for a new job. –  NickLarsen Dec 21 '10 at 14:50
1  
Only that another accidental automatic formatting would wipe out all that indenting, and time for another round of restructuring - hugely productive :) –  nawfal Apr 23 '13 at 19:43

ReSharper in VS.NET sometimes suggests to replace if...else with the ?: operator.

It seems that ReSharper suggests only if the conditions/blocks are below a certain complexity level, otherwise it sticks with if...else.

share|improve this answer
3  
another great feature I love about ReSharper –  Anonymous Type Dec 20 '10 at 21:39

An example (IMHO) of a valid use:

printf("Success in %d %s\n", nr_of_tries, (nr_of_tries == 1 ? "try" : "tries"));

This results in more readable code than having 2 distinct print statements. Nested examples depend: (understandable ? yes : no)

share|improve this answer
10  
Just keep in mind that if you do this, you're making it hell for whoever has to localize your application. Of course, if that's not a problem, go right ahead. –  Anon. Dec 20 '10 at 20:23
1  
That's my rule of thumb: 1 level of nesting (under some circumstances). –  Oliver Weiler Dec 20 '10 at 22:56

I do not think that the ternary operator is evil.

Here is a gotcha that had me stumped, though. I was a C programmer for many (10+) and in the late 1990s I moved into web based application programming. As a web programmer, I soon ran across PHP which also has a ternary operator. I had a bug in a PHP program which I finally traced to a line of code with a nested ternary operator. It turns out that the PHP ternary operator associated left to right but the C ternary operator (which I was used to) associates right to left.

share|improve this answer

When is ?: appropriate

  • When it makes your code more concise and readable.

and when is it not?

  • When it makes your code unreadable.
  • If you're doing it just to please a refactoring tool like ReSharper and not the person who has to maintain the code

If you have any logic or function calls inside the ternary expression, you're making it horrible to look at.

share|improve this answer

If ... then ... else tends to emphasize the condition and therfore de-emphasize the operations being conditionally done.

the ternary operator is the opposite, it tends to hide the condition and is therfore useful when the operation being done is more important than the condition itself.

There is the minor technical niggle, in some languages, that they aren't quite interchangeble due to one being a statement and one an expression e.g. conditionally initialising consts in C++

share|improve this answer

It has a place. I've worked at a lot of companies where the skill levels of developers range from terrible to wizard. Since the code has to be maintained, and I won't be there forever, I try to write stuff so that it looks like it belongs there (without looking at the comments with my initials, it is extremely rare for you to be able to look at code I've worked on to see where I made changes), and that someone with less skill than myself can maintain it.

While the ternary operator looks nitziffic and way cool, my experience is that line of code is going to be about impossible to maintain. At my current employer, we have products that have been shipping for almost 20 years. I wouldn't use that example anywhere.

share|improve this answer

Not appropriate for that code! IMO it should be used once on a line - more than that and it becomes pretty much unreadable. There may be an exception but I've not seen it yet.

share|improve this answer

I like the shortness of the ternary expression. Just like "if...else" statements they can get difficult to read if used in excess, but most of the time they make the code easier to read.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.