Conditionals are a very important aspect of the syntax of every programming language. If you have been programming for sometime in any of the popular languages, you should already be familiar with the if..elif..else or switch conditional statements. They are very useful for making decisions in programs.
For example, let’s say a treasure chest has been designed such that only Glad (that’s me) should be able to open it. This logic can be programmatically represented (in Python) as follows:
Expressions vs Statements
For example: literals, assignments, function expressions, logical, bitwise or arithmetic operations, object property access, function invocations, eval, etc.
For example: conditionals, variable or function declarations, loops, throw, return, try/catch/finally, etc.
Conditions and Booleans
A critical requirement of every conditional is the condition. The condition is what determines the decision to be made in the program.
Here are two fundamental concepts that can enable us to understand the conversions:
Identifying truthy and falsy values
Understanding short-circuiting in logical operations
Truthy vs Falsy
'' or "" or ``(an empty string)
0 or -0 (the number 0)
However, if you want to be deliberate or explicit about the type coercion, you can use the native Boolean function to convert any value its corresponding boolean.
You can also use the logical NOT (!) operator to convert a value to a boolean. The ! operator converts it’s operand to the inverse boolean value, hence, it always evaluates to a boolean value.
Using the ! operator evaluates to false on truthy values and true on falsy values. To convert a value to its corresponding boolean, you need to use the ! operator twice.
The AND (&&) and OR (||) logical operators both require two operands, and are used to perform Boolean operations on their operands.
Given that the two operands are booleans (true or false),
&& operation returns true only when both operands are true, otherwise it returns false.
|| operation returns false only when both operands are false, otherwise it returns true.
Note that the && operator has a higher precedence than the || operator, and as such, is usually evaluated first. Hence, when they are used together in an expression, you may use parentheses (()) for grouping in order to alter the evaluation order. Consider the following code snippet:
When using these operators, the first operand is always evaluated. However, the second operand may never be evaluated depending on the result from evaluating the first operand. This behavior is known as short-circuiting.
The && and || operations do not always produce a boolean value. Generally, they can produce just any value. Here is a more concise description of their behavior based on short-circuiting:
&& operator first evaluates its first operand. If the resulting value is truthy, it evaluates the second operand and returns its value. However, if the value of the first operand is falsy, the second operand is never evaluated, it just returns the falsy value from the first operand.
|| operator first evaluates its first operand. If the resulting value is truthy, the second operand is never evaluated, it just returns the truthy value from the first operand. However, if the value of the first operand is falsy, it evaluates the second operand and returns its value.
Replacing Statements with Expressions
You now have a clear understanding of the short-circuiting concept and how condition expressions get converted to booleans.
Next, you will see how some conditional statements can be converted to simple expressions. You will also see how such conversions can make your code look more compact and cleaner.
1. Simple If Statements
Very simple if statements can easily be replaced with conditional expressions by leveraging on the concept of short-circuiting. Consider the following code snippet:
In this code snippet, the if statement ensures that the deletePost()function is only invoked when the condition evaluates to true.
This simple if statement can be replaced with a very simple conditional expression as shown in the following code snippet:
Though this conditional expression works in a similar fashion as the previous if statement, they are actually different.
The conditional expression produces a value, which means it can be assigned to a variable, or used any other place where a value is required.
Remember that using conditional expressions like this means you have to be very careful about short-circuiting caveats. It is very possible that an operand may not be evaluated as we saw in the previous section on short-circuiting.
2. If…Else Statements
Consider the following dummy code snippet for determining the strength of a password:
The intent of this code snippet is very simple?—?check if the password is more than 7 characters long. If it is, then set the strength variable to “Strong”, otherwise set it to “Weak”.
The previous code snippet can be shortened to the following:
This code snippet does exactly what the previous one does, all in just one line. This looks pretty good already. The following code snippet tries to review the evaluation of the conditional expression.
There is a better way of writing these kinds of if...else conditional expressions?—?using the conditional operator also called the ternary operator. Its syntax looks like the following:
The previous code snippet can hence be rewritten using the ternary operator as follows:
Although the code snippet using logical operators works in a similar fashion as the snippet using the ternary operator (for this example), it is important to know that they are not substitutes.
It is much safer to use the ternary operator for cases like this except you really know what you are doing.
Consider the following code snippet to understand the danger of using logical operators for cases like this:
Here is another very familiar conditional statement that was usually found in cross-browser AJAX libraries.
Using logical operators, the previous code snippet can be rewritten like this (indentations are used to aid readability):
However, using the ternary operator, it can be written like this:
Notice in this code snippet that the ternary operator is nested, which is useful for dealing with more involved if...else conditions.
Tips and Shortcuts
In this section, you will see some helpful tips and shortcuts that can be useful when working with conditions and logical operators.
Normalizing to Boolean
Let’s say you want to normalize value such that you always get a boolean as follows:
If value is a boolean, return value as it is.
If value is not a boolean, default to a boolean value of your choice - either true or false.
The following code snippet shows how this can be done (functions are being used here):
De Morgan’s Laws
The following code snippet demonstrates the laws:
When dealing with booleans, there are some known identities that are always true. Given that A, B and C are boolean values, the following code snippet shows some of these identities.
Multiple Ternary Operators
You have seen in an earlier code snippets that ternary operators can be nested to handle more involved if...else conditional logic.
However, there are a few things you need to know about the precedence and associativity of the ternary operator to enable you use them effectively in complex expressions.
The ternary operator has a lower precedence than logical operators and most other operators. Hence it is evaluated last when used together with operators of higher precedence.
The ternary operator has a right-to-left associativity. Hence, when multiple ternary operators are used in the same expression, they are parsed from right to left.
When using multiple ternary operators in an expression, you may need to use parentheses (()) to alter the evaluation order.