akumar.xyz

Using Ternary Operators

Jan 29, 2023

You know, ternary (conditional) operators!

const a = condition? if_true : if_false;

Ternary operators are probably the most underrated. Being a declarative programming enjoyer, I think people don’t use ternary operators enough even when appropriate. Admittedly,

  1. they’re more “esoteric”
  2. Using imperative if statements makes more sense for how many beginners learn to do coding.

So here’s a few things to help you understand ternary operators better:

1. Consts are better than Vars

Using const makes our code easier to reason. It is part of a much bigger discussion and difficult to explain it in brief, but the everything becomes simpler when we use fewer mutable identifiers (and more constants) in our code (see: further reading).

So, we can replace a pattern like:

char* username;
if (user_is_authenticated(user)) {
    username = user.name;
} else {
    username = "Guest";
}

/* use username */

with so:

const char* 
username = user_is_authenticated(user) 
           ? user.name
           : "Guest";

/* use username */

Note the indentation, do not put everything on the same line

2. Ternary operators are easier to read and write

…once you know how to do it correctly.

Its really a concise way to if-then-else once you get used to it. Situations like these, the only way for somebody to understand what a program is doing is to basically compile it in their head. In such cases, the more terse “mathematic-y” notation is simply better.

3. Never nesting - sometimes

Its easy to make sphagetti when nesting ternary conditionals. See this example

const char*
username = user_is_authenticated(user)
            ? user_is_admin(user)
                ? strcat(user.name, " (Admin)"))
                : user.name
            : "Guest";

This certainly looks better to me compared to a imperative counterpart, but that’s just me. I hope you see how this can get out of hand, very complicated, very quickly.

So this is what you do, take a page from the early return book and invert the conditions. This way, rather than “nesting” ternary operations, you are “chaining” them. This results in an unexpectedly big W for readability

const char*
username = !user_is_authenticated(user)       // if
            ? "Guest"                         // then
            : !user_is_admin(user)            // elif
            ? user.name                       // then
            : strcpu(user.name, " (Admin)");  // else

See? It’s a straightforward if-then-elif-then-else.

Your linter may yell at you, but linters are stupid sometimes. Chained ternary expressions are actually bussin'.

We can make it work with python’s odd x if condtion else y syntax too!

username = ( 
         "Guest"                if user.is_authenticated()
    else f"{user.name} (Admin)" if user.is_admin()
    else user.name
)

Impressive. Very nice. Let’s see black’s formatting

username = (
    "Guest"
    if user.is_authenticated()
    else f"{user.name} (Admin)"
    if user.is_admin()
    else user.name
)

Further Reading

- Adithya Kumar

Tag: programming