We can have more complex conditions but there are a couple of different ways this can happen. First is the condition itself. The actual question we're asking is more complex so we have to ask about two or more things to get down to that single true or false result.
Here’s the first example using just Pseudocode, shown in the upper half of Fig 4.3.1. We're writing some code to calculate the interest on a bank balance but we only want to do this if the account balance is greater than 1000 and also the account type must be a savings. Only if both of these things are true do we want to do this.
Fig 4.3.1: Two examples of complex conditions, one using AND and the other using OR situation
In the second example, shown in the lower half of Fig 4.3.1. We're figuring out if an order on our website qualifies for free shipping and we want to say if either the cartTotal is greater than a 100 or the shopper is a premium member, they get free shipping. The first example is an AND situation and the second is an OR situation.
In both of these, the conditions are each made of two pieces. They're each made of two smaller conditions. The computer is first going to look at each piece separately as a single condition, figuring out if each part is true or false.
In the first example, both of the smaller conditions must evaluate to true, both balance greater than a 1000 and account type equal to savings in order for the larger condition to be considered true. But in the second example, either of the smaller conditions could be considered true for the larger condition to be considered true.
However, in the second example, it is possible they are both true. It's a premium member making a large order, but we don't care. It doesn't matter. Either one by itself would have worked. So, some common syntax with complex conditions, even if you don't have to, it's often useful to surround each inner condition piece in its own set of parentheses such as, (balance > 1000) and (account Type == “savings”), so that it's very clear what you're looking at, as shown in Fig 4.3.2.
Fig 4.3.2: Common syntax for some complex conditions
Some languages may require the entire condition to be inside one set of parentheses, as shown in the first line of the code in Fig 4.3.2. A few languages actually use the words AND and OR as the keywords between each smaller conditions. But in many languages it is two ampersands (&&) written together to mean AND, and two of the vertical bar symbols (||) written to represent OR.
Having said that, you're not limited to do it. You can take this further. You can have multiple smaller conditions (condition1, condition2, condition3, etc) separated by && and/or || as shown in Fig 4.3.2.
There is another type of situation where we want more than just two possibilities. One single if block with one single ELSE block is not good enough. Now first it is common to add additional ifs as part of the same situation, even one inside another to go deeper to ask multiple levels of question.
To really grasp this idea, forget about syntax for a moment. Think about this in terms of shopping. You see, not all situations are as black and white as this:
“We’ll go to the store and if they have full-fat milk, we'll buy that. Otherwise we’ll buy skimmed milk”.
Life gets a little deeper. So as Pseudocode for this, I'm going to add a new if/ELSE inside the original ELSE block. See Fig 4.3.3.
Fig 4.3.3: Creating multiple branches by adding one more if/ELSE block
So now I can ask a deeper question. If they don't have full fat then do they have 2%? If they don't have that, then we'll buy skimmed milk.
Okay. This is a way I can easily deal with three options or three eventualities rather than two. It can get even deeper than this. Let’s take Fig 4.3.4 as another example.
Nested If Statements
Fig 4.3.4: Creating multiple branches by adding nested “if statements”
These are nested “if statements”; they are self contained “if” or “if/Else” statements written inside the block of another if/Else statement. Technically you could keep on nesting ifs inside other ifs. You can go 5, 10, 20 levels deep. Most programming style guides caution against going more than two, or perhaps three levels.
That is because they do become difficult to read and difficult to be confident that every eventuality will be reached correctly. There's a couple of things that plain if statements are not great at. One is when you're working with a range of values in your data.
Dealing with Ranges
For example, a temperature that might fall into a different range of acceptable and unacceptable values. You could check this with nested ifs, but it's kind of annoying to read or write.
Fig 4.3.5: Creating range of temperatures with nested “if statements”
Alternatively, you could just write one separate if statement after another, as shown in Fig 4.3.6. But one thing to be careful about with multiple disconnected if statements is that it's that it's really easy to miss things and make errors in your logic.
Fig 4.3.6: Creating range of temperatures with separate “if statements”
In the situation in Fig 4.3.6 for example, if the temperature was exactly 90 none of these messages would be output because there's one option to deal with less than (<) 90 and one to deal with more than (>) 90 but not 90 itself. Also, if the temperature was exactly a 110 two of these messages would be output.
The issue is that the language isn't going to alert you about this. It'll assume that's what you want. So, because checking the same piece of data from multiple possible values gets tedious with if statements, there’s a better way in many languages.
It’s what's usually called a switch statement, though it can also be called a case or select statement. It's designed for exactly this kind of situation where we're looking at one thing, one piece of data, but describing multiple possible options for it. An example is shown in Fig 4.3.7.
Fig 4.3.7: Creating range of temperatures with switch statement
This is all one switch statement that spans multiple lines. At the top we say what we're looking at, that is, we switch on one particular thing, in this case the variable bath temperature. Then within the block we have multiple, different cases or values to check against. There is a different code we can execute in each case.
Usually we are offering a catch-all option at the bottom, such as print (“Are you … lobster?”), to handle the case where none of the specific values were matched.
Now, switch statements are implemented a little differently across languages. Some allow you to define ranges to check for, others make you list every separate value you're looking for. See Fig 4.3.8.
Fig 4.3.8: Creating range of temperatures with switch statement by defining ranges to check for
I won't get deeper into them here, but it's good to know this is a much more readable format for dealing with this kind of situation.
Okay. We've talked about ifs, ELSEs, ANDs, ORs, nested ifs and Switches, but these conditional statements are not the only way to affect our code. In the next section, we will discuss iteration, that is, how to repeat it or loop.