202

I'm personally an advocate of the ternary operator: () ? :

I do realize that it has its place, but I have come across many programmers that are completely against ever using it, and some that use it too often.

What are your feelings on it? What interesting code have you seen using it?

informatik01
  • 16,038
  • 10
  • 74
  • 104
pixel
  • 5,298
  • 8
  • 35
  • 32
  • 9
    Use it when it's clear, avoid it when it confuses. That's a judgment call. It can make code more readable, but only for simple expressions. Trying to *always* use it is just as much a menace as relentlessly avoiding it. – Abel Nov 05 '09 at 04:40
  • 4
    Actually, it's the conditional operator. A close-to-duplicate question is http://stackoverflow.com/questions/725973/what-do-fellow-net-developers-think-about-the-conditional-operator/726005. – Daniel Daranas Oct 28 '11 at 22:22
  • I was sometimes using `x = x if x else y` but then asked about it and realized with others help that it really just reduces to x = x or y (http://stackoverflow.com/questions/18199381/self-referencing-ternary/18199562#18199562) – Scruffy Aug 14 '13 at 13:45
  • The ternary operator can be used in places where the **if..else** construct can't, for example in return statements, and as function arguments. The same could be achieved without ternary use, but results in longer code and larger executables. – Arif Burhan Mar 01 '16 at 03:02

54 Answers54

268

Use it for simple expressions only:

int a = (b > 10) ? c : d;

Don't chain or nest ternary operators as it hard to read and confusing:

int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;

Moreover, when using ternary operator, consider formatting the code in a way that improves readability:

int a = (b > 10) ? some_value                 
                 : another_value;
marcospereira
  • 12,045
  • 3
  • 46
  • 52
  • 99
    Totally agree with the first few statements but totally disagree with your example of "improved readability". If you're going for multi-line why not just use an if statement? – Joe Phillips Oct 02 '09 at 02:19
  • 5
    just because if else is a quite more verbose for simple decisions: int a = 0; if(b > 10) a = some_value; else a = another_value; What do you prefer? – marcospereira Oct 05 '09 at 17:34
  • 48
    @d03boy: Because if-statement is just that, a statement, and won't do when all you want is an expression. – falstro Feb 16 '10 at 19:10
  • 2
    @roe in some languages if is expression (e.g. in Scala), so `val x = if(true) 0 else 1` is perfectly legal – om-nom-nom Dec 04 '12 at 21:07
  • 6
    @om-nom-nom case in point, that would make it an if-expression, rather than an if-statement, and is essentially the same thing as the ?:-operator. – falstro Dec 07 '12 at 15:59
  • Surely the main point to consider is who will be maintaining the code after, since it is mainly a question of readability. Ternary operators are understood by less people, one of your aims when coding should be to make your work as clear and easy to understand as possible. – ThePerson Feb 14 '14 at 13:46
  • I personally favour either 1-line expressions – mr_T Nov 05 '14 at 12:18
  • 2
    One of theproblems with if is that it's easy to pollute. An if can contain any statement, ?: is an expression returning a value. You very rarely are tempted to add side effects to it, for instance. – Volker Apr 18 '17 at 10:38
  • 1
    Debuggers (most) won't help with even the most simple of ternary operations – Jacksonkr Mar 05 '18 at 21:55
  • @falstro except for python where ternary does not exist, and you still use if even for expressions – Máxima Alekz Jun 14 '22 at 15:43
  • @MáximaAlekz python has a ternary operator, it's just very expressive. (e.g. a = 1 if condition else 0); it's important to note that this is an expression as opposed to your normal ifs which are statements and cannot be assigned to a variable like this. – falstro Jun 15 '22 at 16:03
  • @marcospereira I'd just turn that condition resolve to a function where I can just return instead assigning – Máxima Alekz Jun 16 '22 at 15:06
  • Sadly not always possible. – Spencer Jul 21 '23 at 14:21
160

It makes debugging slightly more difficult since you can not place breakpoints on each of the sub expressions. I use it rarely.

David Segonds
  • 83,345
  • 10
  • 45
  • 66
  • 61
    That's the best argument against the ternary operator I ever heard. I don't buy the "not readable" argument (it sounds to me like people being too lazy to get used to it) but this actually has substance. – EpsilonVector May 03 '10 at 01:03
  • 5
    If you're doing anything inside a ternary that requires debugging, then it's probably being used wrong. Ternaries should be for simple assignment IMO. If you need to step through the ternary, and seeing the value of the assignment afterwards is not enough, the ternary is NOT your actual problem. It's the complexity of the operation. Make it an if statement at that point. – Julian Oct 09 '20 at 15:19
83

I love them, especially in type-safe languages.

I don't see how this:

int count = (condition) ? 1 : 0;

is any harder than this:

int count;

if (condition)
{
  count = 1;
}
else
{
  count = 0;
}

I'd argue that ternary operators make everything less complex and more neat than the alternative.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ian P
  • 12,840
  • 6
  • 48
  • 70
  • 6
    Ternary initialization is even more useful in D or C++ when the variable is constant. eg `const int count = ...;` – deft_code Feb 15 '11 at 16:51
  • Well, you're kind of misrepresenting `if/else` with the unneeded braces there. – bobobobo Dec 20 '12 at 23:12
  • 1
    Also, in this case if `condition` is `bool` [you could just do](http://stackoverflow.com/questions/4276207/is-c-c-bool-type-always-guaranteed-to-be-0-or-1-when-typecasted-to-int) `int count = condition;` – bobobobo Dec 20 '12 at 23:14
  • 1
    @bobobobo this `if/else` with braces is how the majority of programmers will rewrite the ternary.. – Andre Figueiredo Mar 25 '14 at 21:12
  • 2
    @bobobobo if/else w/o braces is just asking for trouble. It's far too easy for someone to add a line, but forget that it'll then need braces to do what they expect (execute the additional line as part of a block): https://stackoverflow.com/a/381274/377225 – George Marian Mar 09 '19 at 02:32
  • @GeorgeMarian Marian: Yes, that is why most coding standard have them as a requirement. Related: *[Learning from Apple's #gotofail security bug](http://avandeursen.com/2014/02/22/gotofail-security/)* - *"Insisting on curly braces would highlight the fault even more"* – Peter Mortensen Oct 27 '20 at 18:22
48

Chained I'm fine with - nested, not so much.

I tend to use them more in C simply because they're an if statement that has value, so it cuts down on unnecessary repetition or variables:

x = (y < 100) ? "dog" :
    (y < 150) ? "cat" :
    (y < 300) ? "bar" : "baz";

rather than

     if (y < 100) { x = "dog"; }
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; }
else              { x = "baz"; }

In assignments like this, I find it's less to refactor, and clearer.

When I'm working in ruby on the other hand, I'm more likely to use if...else...end because it's an expression too.

x =   if (y < 100) then "dog"
    elif (y < 150) then "cat"
    elif (y < 300) then "bar"
    else                "baz"
    end

(Although, admittedly, for something this simple, I might just use the ternary operator anyway.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rampion
  • 87,131
  • 49
  • 199
  • 315
41

The ternary ?: operator is merely a functional equivalent of the procedural if construct. So as long as you are not using nested ?: expressions, the arguments for/against the functional representation of any operation applies here. But nesting ternary operations can result in code that is downright confusing (exercise for the reader: try writing a parser that will handle nested ternary conditionals and you will appreciate their complexity).

But there are plenty of situations where conservative use of the ?: operator can result in code that is actually easier to read than otherwise. For example:

int compareTo(Object object) {
    if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
       return 1;
    if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
       return -1;
    else
      return 0;
}

Now compare that with this:

int compareTo(Object object) {
    if(isLessThan(object))
        return reverseOrder ? 1 : -1;
    else(isGreaterThan(object))
        return reverseOrder ? -1 : 1;
    else
       return 0;
}

As the code is more compact, there is less syntactic noise, and by using the ternary operator judiciously (that is only in relation with the reverseOrder property) the end result isn't particularly terse.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ryan Delucchi
  • 7,718
  • 13
  • 48
  • 60
  • i would still advocate using accolades on every if/then/else construction that is not ternary tho, so your second example is missing a few imho. – Kris May 27 '09 at 14:05
  • Yes, it is functional. It's like a tiny function that has a single boolean argument and, returns _any_ type you want! Actually a neat operator. – bobobobo Feb 19 '12 at 17:38
24

It's a question of style, really; the subconscious rules I tend to follow are:

  • Only evaluate 1 expression - so foo = (bar > baz) ? true : false, but NOT foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
  • If I'm using it for display logic, e.g. <%= (foo) ? "Yes" : "No" %>
  • Only really use it for assignment; never flow logic (so never (foo) ? FooIsTrue(foo) : FooIsALie(foo) ) Flow logic in ternary is itself a lie, ignore that last point.

I like it because it's concise and elegant for simple assignment operations.

Keith Williams
  • 507
  • 1
  • 3
  • 5
  • In C# you can use it for flow control if you're assigning a delegate from within the ternary, and then invoking it afterwards. Well, that's kind of flow control... – Erik Forbes Oct 30 '08 at 04:48
  • 25
    Your two first examples are really bad. The results of comparisons are already boolean values, so your ternary operators are useless and only complicate the code. – Trillian Nov 08 '09 at 16:51
  • 1
    @Trillian +1 Yes, should have gone with a different assignment. `foo = (bar > baz);` is much simpler – Eric Jan 27 '12 at 14:09
  • For the case of the boolean return with a bunch of clauses, I like to break the requirements up into smaller bits using the ternary conditional, kind of like when you refactor by using early returns to simplify code. `return bar <= baz ? false ! lotto ? false : someArray.Contains(someValue ) ` – daotoad Mar 04 '19 at 19:20
18

Like so many opinion questions, the answer is inevitably: it depends

For something like:

return x ? "Yes" : "No";

I think that is much more concise (and quicker for me to parse) than:

if (x) {
    return "Yes";
} else {
    return "No";
}

Now if your conditional expression is complex, then the ternary operation is not a good choice. Something like:

x && y && z >= 10 && s.Length == 0 || !foo

is not a good candidate for the ternary operator.

As an aside, if you are a C programmer, GCC actually has an extension that allows you to exclude the if-true portion of the ternary, like this:

/* 'y' is a char * */
const char *x = y ? : "Not set";

Which will set x to y assuming y is not NULL. Good stuff.

Sean Bright
  • 118,630
  • 17
  • 138
  • 146
  • Fixed slight syntax and grammar prob, Sean :-) Missing y from last bit of code and "assign x to y" means "y = x", so I chgd to "set x to y". – paxdiablo Feb 11 '09 at 01:55
  • @Pax: Thanks! I rolled back the syntax change since I was trying to point out that with GCC extensions you don't need the if-true portion of the ternary. – Sean Bright Feb 11 '09 at 01:56
  • Sorry, didn't see that paragraph. Don't know that I agree with that sort of stuff though since it allows people to write code that won't compile with a ISO-standard compiler. Still, when GCC is the last man standing, that won't matter :-) – paxdiablo Feb 11 '09 at 02:00
  • It is voodoo, for sure... And who doesn't use GCC? :D – Sean Bright Feb 11 '09 at 02:01
14

In my mind, it only makes sense to use the ternary operator in cases where an expression is needed.

In other cases, it seems like the ternary operator decreases clarity.

John Mulder
  • 9,765
  • 7
  • 33
  • 37
  • the problem being that is 99% of the language, an expression can be replaced by a function ... and ppl avoiding the ternary operator will even prefer that solution. – PierreBdR Oct 01 '08 at 23:32
11

I use the ternary operator wherever I can, unless it makes the code extremely hard to read, but then that's usually just an indication that my code could use a little refactoring.

It always puzzles me how some people think the ternary operator is a "hidden" feature or is somewhat mysterious. It's one of the first things I learnt when I start programming in C, and I don't think it decreases readability at all. It's a natural part of the language.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ilitirit
  • 16,016
  • 18
  • 72
  • 111
11

By the measure of cyclomatic complexity, the use of if statements or the ternary operator are equivalent. So by that measure, the answer is no, the complexity would be exactly the same as before.

By other measures such as readability, maintainability, and DRY (don't repeat yourself), either choice may prove better than the other.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
10

I use it quite often in places where I'm constrained to work in a constructor - for example, the new .NET 3.5 LINQ to XML constructs - to define default values when an optional parameter is null.

Contrived example:

var e = new XElement("Something",
    param == null ? new XElement("Value", "Default")
                  : new XElement("Value", param.ToString())
);

or (thanks asterite)

var e = new XElement("Something",
    new XElement("Value",
        param == null ? "Default"
                      : param.ToString()
    )
);

No matter whether you use the ternary operator or not, making sure your code is readable is the important thing. Any construct can be made unreadable.

Erik Forbes
  • 35,357
  • 27
  • 98
  • 122
  • Or... var e = new XElement("Something", new XElement("value", param == null ? "Default" : param.toString())); – asterite Oct 01 '08 at 23:36
8

I agree with jmulder: it shouldn't be used in place of a if, but it has its place for return expression or inside an expression:

echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;

The former is just an example, and better internationalisation and localisation support of plural should be used!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PhiLho
  • 40,535
  • 6
  • 96
  • 134
6

(Hack of the day)

#define IF(x) x ?
#define ELSE :

Then you can do if-then-else as expression:

int b = IF(condition1)    res1
        ELSE IF(condition2)  res2
        ELSE IF(conditions3) res3
        ELSE res4;
GDP
  • 8,109
  • 6
  • 45
  • 82
John John
  • 1
  • 1
  • 1
6

If you're using the ternary operator for a simple conditional assignment I think it's fine. I've seen it (ab)used to control program flow without even making an assignment, and I think that should be avoided. Use an if statement in these cases.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
5

I think the ternary operator should be used when needed. It is obviously a very subjective choice, but I find that a simple expression (specially as a return expression) is much clearer than a full test. Example in C/C++:

return (a>0)?a:0;

Compared to:

if(a>0) return a;
else return 0;

You also have the case where the solution is between the ternary operator and creating a function. For example in Python:

l = [ i if i > 0 else 0 for i in lst ]

The alternative is:

def cap(value):
    if value > 0:
        return value
    return 0
l = [ cap(i) for i in lst ]

It is needed enough that in Python (as an example), such an idiom could be seen regularly:

l = [ ((i>0 and [i]) or [0])[0] for i in lst ]

this line uses properties of the logical operators in Python: they are lazy and returns the last value computed if it is equal to the final state.

PierreBdR
  • 42,120
  • 10
  • 46
  • 62
5

I've seen such beasts like (it was actually much worse since it was isValidDate and checked month and day as well, but I couldn't be bothered trying to remember the whole thing):

isLeapYear =
    ((yyyy % 400) == 0)
    ? 1
    : ((yyyy % 100) == 0)
        ? 0
        : ((yyyy % 4) == 0)
            ? 1
            : 0;

where, plainly, a series of if-statements would have been better (although this one's still better than the macro version I once saw).

I don't mind it for small things like:

reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;

or even slightly tricky things like:

printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • How can you say a series of *isolating* if statements would be more readable? I read your "beast" *just fine*. `reportedAge` is the example that takes some some figuring--probably because it's more of a particular case than figuring out `isThisYearALeapYear` – Axeman Mar 11 '11 at 15:08
4

I almost never use the ternary operator, because whenever I do use it, it always makes me think a lot more than I have to later when I try to maintain it.

I like to avoid verbosity, but when it makes the code a lot easier to pick up, I will go for the verbosity.

Consider:

String name = firstName;

if (middleName != null) {
    name += " " + middleName;
}

name += " " + lastName;

Now, that is a bit verbose, but I find it a lot more readable than:

String name = firstName + (middleName == null ? "" : " " + middleName)
    + " " + lastName;

Or:

String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;

It just seems to compress too much information into too little space, without making it clear what's going on. Every time I saw the ternary operator used, I have always found an alternative that seemed much easier to read... then again, that is an extremely subjective opinion, so if you and your colleagues find ternary very readable, go for it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike Stone
  • 44,224
  • 30
  • 113
  • 140
  • 1
    That's not exactly the same thing though. In the second example you're compressing all three statements into one line. That is what decreases readability, not the ternary operator. – ilitirit Oct 01 '08 at 23:54
  • Fair enough, I updated to incorporate your comment, but it still just feels cluttered to me... but again, it's subjective... I'm not saying ternary is not readable, I'm saying it's not readable to me (99% of the time) – Mike Stone Oct 01 '08 at 23:57
4

I like using the operator in debug code to print error values so I don't have to look them up all the time. Usually I do this for debug prints that aren't going to remain once I'm done developing.

int result = do_something();
if( result != 0 )
{
  debug_printf("Error while doing something, code %x (%s)\n", result,
                result == 7 ? "ERROR_YES" :
                result == 8 ? "ERROR_NO" :
                result == 9 ? "ERROR_FILE_NOT_FOUND" :
                "Unknown");
}
indiv
  • 17,306
  • 6
  • 61
  • 82
4

I like them. I don't know why, but I feel very cool when I use the ternary expression.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JimDaniel
  • 12,513
  • 8
  • 61
  • 67
3

Well, the syntax for it is horrid. I find functional ifs very useful, and they often makes code more readable.

I would suggest making a macro to make it more readable, but I'm sure someone can come up with a horrible edge case (as there always is with C++).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marcin
  • 48,559
  • 18
  • 128
  • 201
  • many BASIC implementations and variants have an IF function that takes the place of the ternary operator. I have seen a number of codebases with that defined as a macro in C. – Sparr Oct 01 '08 at 23:50
  • Well, I was thinking of functional programming languages, but yes. – Marcin Oct 01 '08 at 23:59
  • "Making a macro to make it more readable," you're quite the joker! – niXar Jan 07 '09 at 23:21
3

I treat ternary operators a lot like GOTO. They have their place, but they are something which you should usually avoid to make the code easier to understand.

Dan Walker
  • 7,123
  • 6
  • 30
  • 24
3

I typically use it in things like this:

before:

if(isheader)
    drawtext(x, y, WHITE, string);
else
    drawtext(x, y, BLUE, string);

after:

    drawtext(x, y, isheader == true ? WHITE : BLUE, string);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
KPexEA
  • 16,560
  • 16
  • 61
  • 78
  • Of course in most languages, you wouldn't need the "==true" part of that ternary either. – Michael Haren Oct 02 '08 at 03:16
  • I realize that, although I tend to put it in just to make the code more readable since the compiler should optimize it to the same thing as without the ==true anyways – KPexEA Oct 02 '08 at 16:49
  • in *no* language can you possibly need "==true" – niXar Jan 07 '09 at 23:13
  • I had hard times deciding whether to upvote or not. The example is nice but the ==TRUE is something I can't stand seeing in other people's code. – Peter Perháč Jan 21 '10 at 10:40
3

As others have pointed out they are nice for short simple conditions. I especially like them for defaults (kind of like the || and or usage in JavaScript and Python), e.g.

int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;

Another common use is to initialize a reference in C++. Since references have to be declared and initialized in the same statement you can't use an if statement.

SomeType& ref = pInput ? *pInput : somethingElse;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maccullt
  • 2,769
  • 1
  • 18
  • 15
  • 2
    Amazing that this is the first mention of initialising references, which is one of the few places where "if" cannot be used instead of ?:. (I guess because this is not a C++-specific question...) They are also useful in constructor initialisation lists, for the same reason. – j_random_hacker Feb 11 '09 at 04:26
2

I recently saw a variation on ternary operators (well, sort of) that make the standard "() ? :" variant seem to be a paragon of clarity:

var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]

or, to give a more tangible example:

var Name = ['Jane', 'John'][Gender == 'm'];

Mind you, this is JavaScript, so things like that might not be possible in other languages (thankfully).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
pilsetnieks
  • 10,330
  • 12
  • 48
  • 60
  • 1
    wow, that's awful! imagine nesting a couple of those together! The only vaguely useful thing I can see with that is if you had a function which returned a 2-element array: var Name = getNames()[Gender == 'm']; ...but that's even LESS readable! – nickf Oct 02 '08 at 02:03
2

Only when:

$var = (simple > test ? simple_result_1 : simple_result_2);

KISS.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

For simple if cases, I like to use it. Actually it's much easier to read/code for instance as parameters for functions or things like that. Also to avoid the new line I like to keep with all my if/else.

Nesting it would be a big no-no in my book.

So, resuming, for a single if/else I'll use the ternary operator. For other cases, a regular if/else if/else (or switch).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rodrigo Gómez
  • 1,079
  • 8
  • 24
2

I like Groovy's special case of the ternary operator, called the Elvis operator: ?:

expr ?: default

This code evaluates to expr if it's not null, and default if it is. Technically it's not really a ternary operator, but it's definitely related to it and saves a lot of time/typing.

Steve Losh
  • 19,642
  • 2
  • 51
  • 44
  • Yeah, I love that one as well - it's `??` in C#, the null coalesce operator: http://stackoverflow.com/questions/278703/unique-ways-to-use-the-null-coalescing-operator – Jarrod Dixon Oct 02 '09 at 02:32
2

For simple tasks, like assigning a different value depending on a condition, they're great. I wouldn't use them when there are longer expressions depending on the condition though.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Svet
  • 3,555
  • 8
  • 28
  • 23
2

If you and your workmates understand what they do and they aren't created in massive groups I think they make the code less complex and easier to read because there is simply less code.

The only time I think ternary operators make code harder to understand is when you have more than three or foyr in one line. Most people don't remember that they are right based precedence and when you have a stack of them it makes reading the code a nightmare.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alex
  • 34,776
  • 10
  • 53
  • 68
2

As so many answers have said, it depends. I find that if the ternary comparison is not visible in a quick scan down the code, then it should not be used.

As a side issue, I might also note that its very existence is actually a bit of an anomaly due to the fact that in C, comparison testing is a statement. In Icon, the if construct (like most of Icon) is actually an expression. So you can do things like:

x[if y > 5 then 5 else y] := "Y"

... which I find much more readable than a ternary comparison operator. :-)

There was a discussion recently about the possibility of adding the ?: operator to Icon, but several people correctly pointed out that there was absolutely no need because of the way if works.

Which means that if you could do that in C (or any of the other languages that have the ternary operator), then you wouldn't, in fact, need the ternary operator at all.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
staticsan
  • 29,935
  • 4
  • 60
  • 73
1

My recently formulated rule of thumb for determining whether you should use the ternary operator is:

  • if your code is choosing between two different values, go ahead and use the ternary operator.
  • if your code choosing between two different code paths, stick to an if statement.

And be kind to readers of your code. If you are nesting ternary operators, format the code to make that nesting obvious.

Travis
  • 576
  • 5
  • 13
1

The ternary operator hands down. They aren't complex if you format properly. Take the leap year example from paxdiablo:

$isLeapYear =
   (($year % 400) == 0)
   ? 1
   : ((($year % 100) == 0)
      ? 0
      : ((($year % 4) == 0)
         ? 1
         : 0));

This can be written more concise and be made much more readable with this formatting:

//--------------Test expression-----Result
$isLeapYear = (($year % 400) == 0) ? 1 :
              ((($year % 100) == 0)? 0 :
              ((($year % 4) == 0)  ? 1 :
                                     0)); // Default result
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jeremysawesome
  • 7,033
  • 5
  • 33
  • 37
1

I would say that the number of conditions in a logic expression make it harder to read. This is true of an if statement and this is true of a ternary operator. In a perfect world, there should be one summarizable reason for taking a branch as opposed to others. Chances are that it really is more of a "business rule" if your explanation is "only when this cluster of states occur".

However, in the real world, we don't add intermediate steps to fold states into one expressible state simply to obey the ideal case. We have made inferences about multiple states and have to make a decision on how to handle them.

I like ternaries because it's possible to do anything with an if statement.

if( object.testSomeCondition()) {
    System.exec( "format c:" );
}
else {
    a++;
}

On the other hand:

a += ( object.testSomeCondition() ? 0 : 1 );

makes it clear that the goal is to find a value for a. Of course, in line with that, there probably shouldn't be more than reasonable side effects.

  • I use an if for long or complex conditions after I've decided whether I have the time to rework conditions upstream so that I'm answering an easier question. But when I use an if, I still try to do parallel processing, just under a different condition.

      if (  user.hasRepeatedlyPressedOKWithoutAnswer()
         && me.gettingTowardMyLunchtime( time )
         ) {
          ...
      }
    
  • Also my goal is near-single-stream processing. So I often try not to do an else and an if is simply a step off the common path. When you do a lot of single-stream processing, it's much harder for bugs to hide in your code waiting for that one condition that will jump out and break things.

  • As I said above, if you use a ternary to set one thing, or you have a small number of cases you want to test in order to set it to a value, then I just like the readability of a ternary.

  • With one caveat--> NO COMPLEX true CLAUSES

      a = b == c ? ( c == d ? ( c == e ? f : g ) : h ) : i;
    

Of course that can be decomposed into:

a = b != c ? i
  : c != d ? h
  : c == e ? f
  :          g
  ;

And it looks like a (compressed) truth table.

Remember that there are more important factors for readability. One of them is block length and another is indentation level. Doing simple things in ternaries doesn't create an impetus to further and further levels of indentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Axeman
  • 29,660
  • 2
  • 47
  • 102
1

No. They are hard to read. If/Else is much easier to read.

This is my opinion. Your mileage may vary.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Genericrich
  • 4,611
  • 5
  • 36
  • 55
1

Use it to:

  • access object (array) properties:

    var status = statuses[error == null ? 'working' : 'stopped'];
    
  • return statements:

    function getFullName(){
        return this.isMale() ? "Mr. " : "Ms. " + this.name;
    }
    
  • initialize variables:

    var formMethod = DEBUG_FLAG == true ? "GET" : "POST";
    
  • validate arguments:

    function(object){
        var prop1 = typeof object.property == 'undefined'
                  ? "default prop"
                  : object.property;
        //...
    }
    

Code examples are in JavaScript.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gion_13
  • 41,171
  • 10
  • 96
  • 108
0

Interesting anecdote: I have seen the optimizer weigh the ternary operator as less "heavy" for the purposes of inlining than the equivalent if. I noticed this with Microsoft compilers, but it could be more widespread.

In particular functions like this would inline:

int getSomething()
{
    return m_t ? m_t->v : 0;
}

But this wouldn't:

int getSomething()
{
    if( m_t )
        return m_t->v;
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Don Neufeld
  • 22,720
  • 11
  • 51
  • 50
0

I like it a lot. When I use it, I write it like an if-then-else: one line each for condition, true action, and false action. That way, I can nest them easily.

Example:

x = (a == b
     ? (sqrt(a) - 2)
     : (a*a + b*b)
     );

x = (a == b
     ? (sqrt(a) - 2)
     : (a*a + b*b)
     );
x = (a == b
     ? (c > d
        ? (sqrt(a) - 2)
        : (c + cos(d))
       )
     : (a*a + b*b)
     );

To me, this is reasonably easy to read. It also makes it easy to add subcases or change existing cases.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

I use and recommend ternaries to avoid code lines in situations where the logic is trivial.

int i;
if( piVal ) {
    i = *piVal;
} else {
    i = *piDefVal;
}

In the above case I would choose a ternary, because it has less noise:

int i = ( piVal ) ? *piVal : *piDefVal;

Likewise conditional return values are good candidates:

return ( piVal ) ? *piVal : *piDefVal;

I think compactness can improve readability which in turn helps to improve the code quality.

But readability always depends on the code's audience.

The readers must be able to understand the a ? b : c pattern without any mental effort. If you can not presume this, go for the long version.

mar10
  • 14,320
  • 5
  • 39
  • 64
  • I agree. Once you understand how they work, it is way more readable. Ternary operators are the greatest thing since the foreach loop! –  Oct 02 '08 at 14:08
0

If your ternary operator ends up taking the whole screen width, then I wouldn't use it. I keep it to just checking one simple condition and returning single values:

int x = something == somethingElse ? 0 : -1;

We actually have some nasty code like this in production...not good:

int x = something == (someValue == someOtherVal ? string.Empty : "Blah blah") ? (a == b ? 1 : 2 ): (c == d ? 3 : 4);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ricardo Villamil
  • 5,031
  • 2
  • 30
  • 26
  • There is actually a language where writing string.Empty makes any sense? What happened to ""? – niXar Jan 07 '09 at 23:17
0

One reason no one seems to mention for using the ternary operator, at least in languages, like D, that support type inference is to allow type inference to work for amazingly complicated template types.

auto myVariable = fun();
// typeof(myVariable) == Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)).

// Now I want to declare a variable and assign a value depending on some
// conditional to it.
auto myOtherVariable = (someCondition) ? fun() : gun();

// If I didn't use the ternary I'd have to do:
Foo!(Bar, Baz, Waldo!(Stuff, OtherStuff)) myLastVariable;  // Ugly.
if(someCondition) {
    myLastVariable = fun();
} else {
    myLastVariable = gun():
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dsimcha
  • 67,514
  • 53
  • 213
  • 334
0

I like the operator in some situations, but I think some people tend to overuse it and that it can make the code harder to read.

I recently stumbled across this line in some open source code I am working to modify.

Where

    (active == null ? true :
    ((bool)active ? p.active : !p.active)) &&...

Instead of

where ( active == null || p.active == active) &&...

I wonder if the ternary use adds extra overhead to the LINQ statement in this case.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tim
  • 377
  • 7
  • 19
0

I agree with the sentiments of many of the posters here. The ternary operator is perfectly valid as long as it is used correctly and does not introduce ambiguity (to be fair, you can say that about any operator/construct).

I use the ternary operator often in embedded code to clarify what my code is doing. Take the following (oversimplified for clarity) code samples:

Snippet 1:

int direction = read_or_write(io_command);

// Send an I/O
io_command.size = (direction==WRITE) ? (32 * 1024) : (128 * 1024);
io_command.data = &buffer;
dispatch_request(io_command);

Snippet 2:

int direction = read_or_write(io_command);

// Send an I/O
if (direction == WRITE) {
    io_command.size = (32 * 1024);
    io_command.data = &buffer;
    dispatch_request(io_command);
} else {
    io_command.size = (128 * 1024);
    io_command.data = &buffer;
    dispatch_request(io_command);
}

Here, I am dispatching an input or output request. The process is the same whether the request is a read or a write, only the default I/O size changes. In the first sample, I use the ternary operator to make it clear that the procedure is the same and that the size field gets a different value depending on the I/O direction. In the second example, it is not as immediately clear that the algorithm for the two cases is the same (especially as the code grows much longer than three lines). The second example would be more difficult to keep the common code in sync. Here, the ternary operator does a better job of expressing the largely parallel nature of the code.

The ternary operator has another advantage (albeit one that is normally only an issue with embedded software). Some compilers can only perform certain optimizations if the code is not "nested" past a certain depth (meaning inside a function, you increase the nesting depth by 1 every time you enter an if, loop, or switch statement and decrease it by 1 when you leave it). On occasion, using the ternary operator can minimize the amount of code that needs to be inside a conditional (sometimes to the point where the compiler can optimize away the conditional) and can reduce the nesting depth of your code. In some instances, I was able to re-structure some logic using the ternary operator (as in my example above) and reduce the nested depth of the function enough that the compiler could perform additional optimization steps on it. Admittedly this is a rather narrow use case, but I figured it was worth mentioning anyway.

bta
  • 43,959
  • 6
  • 69
  • 99
  • 1
    Why don't you move io_command.data = &buffer; and dispatch_request(io_command); outside of the if-else statement though? Just place them afterward. Less code duplication. – EpsilonVector May 03 '10 at 01:09
  • This is not fair. The last two statements do not depend on the condition. And should thus not be in the 'if' statement. – Peter Mortensen Oct 27 '20 at 18:59
0

The ternary operator is extremely useful for concisely producing comma separated lists. Here is a Java example:

    int[] iArr = {1, 2, 3};
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < iArr.length; i++) {
        sb.append(i == 0 ? iArr[i] : ", " + iArr[i]);
    }
    System.out.println(sb.toString());

It produces: "1, 2, 3"

Otherwise, special casing for the last comma becomes annoying.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Julien Chastang
  • 17,592
  • 12
  • 63
  • 89
0

If you are trying to reduce the amount of lines in your code or are refactoring code, then go for it.

If you care about the next programmer that has to take that extra 0.1 millisecond to understand the expression, then go for it anyway.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jobo
  • 940
  • 6
  • 11
0

No, ternary operators do not increase complexity. Unfortunately, some developers are so oriented to an imperative programming style that they reject (or won't learn) anything else. I do not believe that, for example:

int c = a < b ? a : b;

is "more complex" than the equivalent (but more verbose):

int c;
if (a < b) {
    c = a;
} else {
    c = b;
}

or the even more awkward (which I've seen):

int c = a;
if (!a < b) {
    c = b;
}

That said, look carefully at your alternatives on a case-by-case basis. Assuming a propoerly-educated developer, ask which most succinctly expresses the intent of your code and go with that one.

joel.neely
  • 30,725
  • 9
  • 56
  • 64
0

I used to be in the “ternary operators make a line un-readable” camp, but in the last few years I’ve grown to like them when used in moderation. Single line ternary operators can increase readability if everybody on your team understands what’s going on. It’s a concise way of doing something without the overhead of lots of curly braces for the sake of curly braces.

The two cases where I don’t like them: if they go too far beyond the 120 column mark or if they are embedded in other ternary operators. If you can’t quickly, easily and readably express what you’re doing in a ternary operator. Then use the if/else equivalent.

Joe Basirico
  • 1,935
  • 16
  • 17
0

It depends :)

They are useful when dealing with possibly null references (BTW: Java really needs a way to easily compare two possibly null strings).

The problem begins, when you are nesting many ternary operators in one expression.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • Actually I disagree with your 'BTW'. Does a NULL string equal another NULL string or not? My opinion is they're not actually strings until they're non-NULL. – paxdiablo Feb 11 '09 at 01:51
  • Maybe I'm a little biased - recently I do mostly eclipse rcp, and I can't count places in code where I've seen variations on this theme: if ( (evt.getNewValue()!=null && evt.getNewValue().equals(evt.getOldValue())) || evt.getNewValue()==evt.getOldValue()) { return; } //do sth –  Feb 11 '09 at 02:03
0

No (unless they're misused). Where the expression is part of a larger expression, the use of a ternary operator is often much clearer.

Denis Hennessy
  • 7,243
  • 4
  • 25
  • 31
0

I think it really depends on the context they are used in.

Something like this would be a really confusing, albeit effective, way to use them:

 __CRT_INLINE int __cdecl getchar (void)
{
   return (--stdin->_cnt >= 0)
          ?  (int) (unsigned char) *stdin->_ptr++
          : _filbuf (stdin);
}

However, this:

c = a > b ? a : b;

is perfectly reasonable.

I personally think they should be used when they cut down on overly verbose IF statements. The problem is people are either petrified of them, or like them so much they get used almost exclusively instead of IF statements.

Onion-Knight
  • 3,477
  • 7
  • 31
  • 34
0

string someSay = bCanReadThis ? "No" : "Yes";

Steven A. Lowe
  • 60,273
  • 18
  • 132
  • 202
0

In small doses they can reduce the number of lines and make code more readable; particularly if the outcome is something like setting a char string to "Yes" or "No" based on the result of a calculation.

Example:

char* c = NULL;
if(x) {
  c = "true";
}else {
  c = "false";
}

compared with:

char* c = x ? "Yes" : "No";

The only bug that can occur in simple tests like that is assigning an incorrect value, but since the conditional is usually simple it's less likely the programmer will get it wrong. Having your program print the wrong output isn't the end of the world, and should be caught in all of code review, bench testing and production testing phases.

I'll counter my own argument with now it's more difficult to use code coverage metrics to assist in knowing how good your test cases are. In the first example you can test for coverage on both the assignment lines; if one is not covered then your tests are not exercising all possible code flows.

In the second example the line will show as being executed regardless of the value of X, so you can't be certain you've tested the alternate path (YMMV depending on the ability of your coverage tools).

This matters more with the increasing complexity of the tests.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adam Hawes
  • 5,439
  • 1
  • 23
  • 30
  • Related to code coverage is the ability to set breakpoints (e.g., a seldom match could be the interesting one during debugging or other analysis). Conditional breakpoints are not always practical or possible. – Peter Mortensen Oct 27 '20 at 18:46
0

Making code smaller doesn't always mean it's easier to parse. It differs from language to language.

In PHP for example, whitespace and line-breaks are encouraged since PHP's lexer first breaks the code up in bits starting with line-breaks and then whitespace. So I do not see a performance issue, unless less whitespace is used.

Bad:

($var)?1:0;

Good:

($var) ? 1 : 0;

It doesn't seem like a big issue, but with lexing code in PHP, whitespace is essential. Plus, it also reads a bit better this way.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SoSo
  • 269
  • 3
  • 4
  • Do you have a source for these claims? E.g. *"PHP's lexer first breaks the code up in bits starting with line-breaks and then whitespace"*. Doesn't PHP have a true parser? What is the actual performance impact of different kind of formatting of PHP code? – Peter Mortensen Oct 27 '20 at 19:09
-1

How would anyone win an obfuscated code contest without the ternary operator?!

I'm personally for using it, when appropriate, but I don't think I'd ever nest it. It's very useful, but it has a couple knocks against it in that it makes code harder to read and is in use in some other languages in other operations (like Groovy's null-check).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
billjamesdev
  • 14,554
  • 6
  • 53
  • 76
-2

I'm a big fan of it ... when appropriate.

Stuff like this is great, and, personally, I don't find it too hard to read/understand:

$y = ($x == "a" ? "apple"
   : ($x == "b" ? "banana"
   : ($x == "c" ? "carrot"
   : "default")));

I know that probably makes a lot of people cringe, though.

One thing to keep in mind when using it in PHP is how it works with a function that returns a reference.

class Foo {
    var $bar;

    function Foo() {
        $this->bar = "original value";
    }

    function &tern() {
        return true ? $this->bar : false;
    }

    function &notTern() {
        if (true) return $this->bar;
        else      return false;
    }
}

$f = new Foo();
$b =& $f->notTern();
$b = "changed";
echo $f->bar;  // "changed"

$f2 = new Foo();
$b2 =& $f->tern();
$b2 = "changed";
echo $f2->bar;  // "original value"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nickf
  • 537,072
  • 198
  • 649
  • 721
  • That's because ternary operator evaluates the result and returns $this -> bar by its value whereas the other one just plain returns the variable. – pilsetnieks Oct 02 '08 at 00:17
  • it's strange how that doesn't cause an error, since you're therefore not returning a reference. – nickf Oct 02 '08 at 02:01