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,
- they’re more “esoteric”
- 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
)