Understanding Ternary Operators: Simplifying Ternary Conditional Logic over If/Else Statements

Introduction

My first encounter with conditional (ternary) operations was when I first ventured into the world of programming. Along my journey, I was tasked with writing a monty program, where I had to define a data structure to use in the program and I relied on my first ever conditional macro, instead of the traditional if … else conditional logic. This is the last line of the code snippet below. This article will focus on Python and JavaScript ternary and conditional expressions. The C code snippet is only an example.

#define USE_STACK 2
#define USE_QUEUE 1
#define USE_DEFAULT 0
/* macro definitions for stack, queue and dataStruct */
#define _stack(opcode) (strcmp((opcode), "stack") == 0)
#define _queue(opcode) (strcmp((opcode), "queue") == 0)
#define _dataStruct(opcode) ((_stack(opcode)) ? USE_STACK : ((_queue(opcode)) ? USE_QUEUE : USE_DEFAULT))

Explanation of conditional logic in programming

Conditional logic in programming is the use of statements or expressions to execute code based on whether certain conditions are true or false. This process or idea allows programs to make decisions, resulting in different actions, depending of varying inputs and or circumstances. Conditional logic is fundamental in programming, allowing for dynamic control flow based on varying conditions. We have all encountered this concept, so long as we make use of software, be it at the low level or as a user who has no idea of any programming concept. A basic use case of conditional logic is form validation. When attempting to log into a service, we are met with either passing valid or invalid input, the outcome of which is based on conditional logic. Example:

user = {
    "username": "Azara",
    "password": "userpwd",
}

def login(user: dict) -> str:
    if user.get("username") and user.get("password"):
        return "Success"
    else:
        return "Invalid Credentials"

Brief overview of if/else statements

if … else statements, perhaps, the most basic and well-known statement type, is the most basic form of conditional logic. Based on the example above, an if statement checks a condition, and if true, executes a block of code. The else statement runs if the condition is false.

age = 18
if age >= 18:
    print("Adult")
else:
    print("Minor")

In the snippet above, the final outcome will be “Adult” because the if statement is a true statement after evaluating the condition age >= 18.

Introduction to ternary operators

What is a Ternary Operator?

Ternary operators are shorthand methods or ways of handling conditional logic in programming. They are frequently used as one-liner alternatives to if … else statements. There, however, are instances where ternary operations span multiple lines. These instances are often noticed in conditional chaining, just as instances where if … else statements are chained using elif as used in python or else if as used in JavaScript. Though conditional chaining of ternary operations span multiple lines, there are much more fewer lines as compared to traditional if … elif … else statements.

Basic syntax

# syntax: x if a > b else y

person = {
    "name": "Azara",
    "city": "Accra",
    "country": "GH",
}

def greeting(person: Dict) -> str:
    name = person.get("name") if person else "stranger"
    city = person.get("city") if person else "unknown"
    country = person.get("country") if person else "unknown"

    greeting_card = f'Hello there, {name}, from the city of {city}!'

    return greeting_card

print(greeting(person))
# Hello there, Azara, from the city of Accra!

The expression x if a > b else y first evaluates the condition, a > b rather than x. If a > b is true, x is evaluated and its value is returned; otherwise, y is evaluated and its value is returned.

Similarly, the expression person.get("name") if person else “stranger” first evaluates the condition, person rather than person.get("name"). If the condition checks, person.get("name") is then evaluated and its value returned; otherwise, “stranger” is returned.

In JavaScript, the syntax is condition ? expressionIfTrue: expressionIfFalse.

  • Condition: The test or logic to evaluate. eg. a > b

  • expressionIfTrue: Result if condition is true.

  • expressionIfFalse: Result if condition is false.

// syntax: condition ? exprIfTrue : exprIfFalse

const person = {
  name: "Azara",
  city: "Accra",
  country: "GH",
};

const greeting = (person) => {
  const name = person ? person.name : "stranger";
  const city = person ? person.city : "unknown";
  const country = person ? person.country : "unknown";

  const greetingCard = `Hello there, ${name}, from the city of ${city}!`;

  return greetingCard;
};

console.log(greeting(person));
// Hello there, Azara, from the city of Accra!

Just like the explanation given for python, the expression condition ? exprIfTrue : exprIfFalse first evaluates the condition. If the condition is true, exprIfTrue is returned; otherwise, exprIfFalse is returned.

Comparison with if/else statements

In python, the one-liner conditional expression person.get("name") if person else "stranger" would have been written using if/else as:

if person:
    name = person.get("name")
else:
    name = "stranger"

And in JavaScript, the one-liner ternary operator person ? person.name : "stranger"; would have been written using if/else as:

if person {
  const name = person.name;
} else {
  const name = "stranger";
}

Notice how in all one-liners we had to declare the name variable to store the person’s name only once, but in the if … else statements, we had to declare the same name variable twice?

Common languages that support ternary operators

We have already seen my example ternary operator which was written in C and subsequent examples that I have elaborated on written in Python and JavaScript. There are other programming languages such as C++, PHP, Java and more that also support ternary operators.

Benefits of Using Ternary Operators

Conciseness and readability

We can attest, based on the examples above, that ternary operators indeed help with code conciseness and code readability. They help reduce code length and squeeze code logic to very fewer lines, making it easy to read when conditions are simple. This is particularly beneficial in short functions or expressions where brevity improves clarity. Instead of writing about 5 lines to check a condition, you can write:

const age = process.argv[1]
const userStatus = (age >= 18) ? "Adult" : "Minor";

or in Python:

age = sys.argv[1]
user_status = "Adult" if age >= 18 else "Minor"

Simplification of simple conditional assignments

Just like in the examples under Comparison with if/else statements, for cases where a variable assignment depends on a condition, ternary operators are perfect for simplifying code. Without the need for an extra code block, you can keep the variable assignment brief and focused.

Enhancing code clarity in certain cases

In instances where conditional logic is easy to understand, using ternary operators add a bit more clarity, helping reduce visual clutter.

When to Use Ternary Operators

Appropriate situations for employing ternary operators

Ternary operators are best used when:

  1. The logic is basic and or simple, like assigning a value based on a condition.

  2. The condition is a straightforward check that does not require nesting.

  3. The use of a ternary operator improves readability without necessarily sacrificing clarity (more on this below).

Examples of effective use cases

<Link to='/cart' className='bg-primary p-1 sm:px-6 px-2 flex items-center rounded-md space-x-2 font-primary'>
    <HiMiniShoppingBag />
        {
            cartItems.length > 0 ? <span className='text-sm font-semibold'>{ cartItems.length }</span> : <span className='text-sm font-semibold'>0</span>
        }
</Link>

I have had to continuously fallback on ternary operators in a bookstore react frontend application I am writing to dynamically display the number of items in a user’s cart. As can be seen in the code snippet above, cartItems.length > 0 is the condition and if the condition is true, we return the cartItems.length value; otherwise, we return a default value, 0.

Removing the span element and the tailwindcss class names, we have a conditional logic being represented by a ternary operator in JavaScript as { cartItems.length > 0 ? cartItems.length : 0 } which if represented in an if/else statement, would look like:

// ternary one-liner
{ cartItems.length > 0 ? cartItems.length : 0 }

// if/else statement
if (cartItems.length > 0) {
  return cartItems.length;
} else {
  return 0;
}

Scenarios where ternary operators should be avoided

Avoid ternary operators when:

  • The condition is complex and involves multiple layers.

  • Nesting multiple ternary operators, as this quickly becomes hard to read and maintain.

  • There’s a need for more than two potential outcomes (use if/else if or switch instead).

Example:

const getGrade = (score) => {
  if (score === 100) {
    return "A++";
  } else if (score >= 90) {
    return "A";
  } else if (score >= 80) {
    return "B";
  } else if (score >= 70) {
    return "C";
  } else if (score >= 60) {
    return "D";
  } else {
    return "F";
  }
};

Nesting the example snippet above, we risk falling into a conditional chaining process;

Conditional chaining refers to the practice of linking multiple conditional statements together, allowing for more complex decision-making processes.

const getGrade = (score) => {
  return (score === 100) ? "A++"
    : (score >= 90) ? "A"
    : (score >= 80) ? "B"
    : (score >= 70) ? "C"
    : (score >= 60) ? "D"
    : "F"
};

We may have managed to reduce the code length from 15 to 7 lines and it looks easy on the eye. But some may have trouble reading the latter example as opposed to the traditional if/else example, especially when we attempt to condense this into a single line. It is a matter of choice, really.

const getGrade = (score) => {
  return (score === 100) ? "A++" : (score >= 90) ? "A" : (score >= 80) ? "B" : (score >= 70) ? "C" : (score >= 60) ? "D" : "F"
};

With the above one-liner example, we can agree that due to the brevity of ternary operators, developers may be tempted to condense overly complicated logic into a single line, reduce code clarity for the next developer who may be required to have access to the same code for dev purposes.

Example of a more complex scenario:

Let us consider an instance where multiple conditions need to be evaluated to determine a user’s access level.

def get_user_access_level(user: dict) -> str:
    if user.get("role") == "admin" and user.get("verified"):
        return "Full Access"
    elif user.get("role") == "editor" and user.get("verified"):
        return "Editor Access"
    elif user.get("role") == "viewer":
        return "View Only"
    else:
        return "No Access"

In the above case, using a nested if/else statement provides a clearer logic than relying on a complex ternary operation like in the JavaScript example below:

const getUserAccessLevel = (user) => {
  return user.role === "admin" && user.verified ? "Full Access"
    : user.role === "editor" && user.verified ? "Editor Access"
    : user.role === "viewer" ? "View Only"
    : "No Access";
};

Conclusion

Ternary operators offers a developer a concise and readable approach to handling simple conditional logic in programming. They are particularly useful for straightforward conditions and variable assignments, reducing code length and enhancing visual clarity when used appropriately. However, avoid ternary operators in complex scenarios where readability might be compromised.

So, a developer should always aim for a balance, using ternary operators where they enhance code clarity and avoiding them when faced with a more complex conditional logic. We can write cleaner and more efficient code when we master the usage of ternary operators, ultimately improving the overall quality of our programming projects.

References:

0
Subscribe to my newsletter

Read articles from Yushahu Yussif Azara directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yushahu Yussif Azara
Yushahu Yussif Azara