# May 16 2021 Ternary operators

Different ways to compose ternary operator to condense if-else statements into expressions in several programming languages

Python has made a concious choice of promoting readability through its syntax. A good example of this is the conditional expression or ternary if-else "operator" in Python. What it means is instead of:

def even_or_odd(x):
if x <= 0:
raise ValueError("Even or odd is defined for positive integers only!")
elif x % 2 == 0:
result = "even"
else:
result = "odd"

return result


you can write in a condensed yet easy to decipher:

def even_or_odd(x):
if x <= 0:
raise ValueError("Even or odd is defined for positive integers only!")

return "even" if x % 2 == 0 else "odd"


If you are new to this, I highly recommend that you use this. It would reduce the indentation in nested if-else statements and need for intermediate variables in more real-life codes.

## In other languages

In C/C++, Java, ECMAScript (a.k.a JavaScript) and possibly more languages the syntax is a bit more terse. It looks like this with ECMAScript:

function even_or_odd(x) {
if (x <= 0) {
throw "Even or odd is defined for positive integers only!"
}
return (x % 2 === 0 ? "even" : "odd")
}


An advantage is that the syntax is more condensed; but as a downside, one needs to remember which side of the colon : assumes the value when the condition is True and vice versa.

## C-style ternary operators using logical operators

I found a trick to create similar obfuscated ternary operators in Python. Here it goes:

def even_or_odd_ugly(x):
if x <= 0:
raise ValueError("Even or odd is defined for positive integers only!")

return x % 2 == 0 and "even" or "odd"


It looks nearly like the C-style ternary operator, but is not at all readable. It works because how the logical boolean operators and, or short-circuits.

In Bash-like shells such expressions can be used to achieve the same effect:

even_or_odd() {
local x=$1 if [[ x -le 0 ]]; then echo "Even or odd is defined for positive integers only!" return 1 fi [[$((x % 2)) == 0 ]] && echo "even" || echo "odd"
}


While writing shell scripts such "ternary operators" are an idiom, because Bash commands returns a non-zero value in case of failure. This would be preferred over use of if-else constructs in Bash which, I think, are complicated in getting the syntax right.

mkdir -p build
./build.sh && echo "Build successful!" || echo "Build failed! Cleaning up ..." && rm -r build


## Bonus: when to avoid if-else statements in Python

We saw a good example of when to use conditional expressions in Python. Now we go on a tangent to look at some features baked into Python which further allow the need for if-else statements.

### Dictionary lookup

# assume the variable color_of_fruits is a dictionary

if "apple" in color_of_fruits:
color = color_of_fruits["apple"]
else:
color = "red"


you could use the oneliner:

color = color_of_fruits.get("apple", "red")


Environment variables of the system are accessed via a special dictionary-like object os.environ. However, for environment variables, there is a handy standard library function os.getenv which is useful. Instead of:

import os

if "CC" in os.environ:
c_compiler = os.environ["CC"]
else:
c_compiler = "gcc"


use:

import os

c_compiler = os.getenv("CC", "gcc")


For both the dict.get method and os.getenv function, if you leave out the default value, you get None and no KeyError would be raised.

### Fall-back values

Whenever you read files, download text from the internet it is not a 100% guarantee that the result would be what you expect. In that case you might need a fall-back value to work with. Take this naive case of reading and printing a file config.cfg which is empty:

def print_config():
with open("config.cfg") as file:
if contents == "":
print("File is empty")
else:
print(contents)


From the previous discussion, we see that we can simplify it using conditional expressions as:

def print_config_conditional():
with open("config.cfg") as file:
print("File is empty" if contents == "" else contents)


However in this case a cleaner option would be to use the short-circuiting property of the or operator to assign a fall-back value.

def print_config_fallback():
with open("config.cfg") as file:
contents = file.read() or "File is empty"
print(contents)


Note that in Python world, evaluating False, "", 0 or None as a part of a boolean expression would mean the same. Also in print_config_fallback, the variable contents is for illustrative purposes and can be avoided.