<h2class="lecturer">LinkedIn Learning : Bill Weinman</h2>
<h2class="episodetitle">Conditionals</h2>
</div>
<article>
<h2class="sectiontitle">The if Statement</h2>
<p>The if statement is the same as you will see in many other programming languages. The basic syntax is shown in the code in figure 30.</p>
<preclass="inset">
1. #!/usr/bin/perl
2. # conditional.pl by Bill Weinman <http://bw.org/contact/>
3.
4. use 5.16.0;
5. use warnings;
6.
7. my $x = 1;
8. my $y = 1;
9.
10. if ( $x == 1 ) {
11. say 'true';
12. }
13.
14. say "x is $x; y is $y";</pre>
<pclass ="caption">Figure 30 - conditional.pl demonstrating the use of a basic if statement</p>
<p>So, we have the if keyword followed by a condition in parentheses and then a block of code. The block of code is executed if the condition evaluates to true.</p>
<p>In this example, the condition is comparing two numbers and so it is using a numerical comparison operator. Perl has different comparison operators for numbers and strings and more information on this can be found here. A table of these operators, taken from the website at Cardiff University, is shown in figure 31.</p>
<table>
<tr>
<th>Equality</th>
<th>Numeric</th>
<th>String</th>
</tr>
<tr>
<td>Equal</td>
<td>= =</td>
<td>eq</td>
</tr>
<tr>
<td>Not Equal</td>
<td>!=</td>
<td>ne</td>
</tr>
<tr>
<td>Comparison</td>
<td><=></td>
<td>cmp</td>
</tr>
</table>
<table>
<tr>
<th>Relational</td>
<th>Numeric</td>
<th>String</td>
</tr>
<tr>
<td>Less than</td>
<td><</td>
<td>lt</td>
</tr>
<tr>
<td>Greater than</td>
<td>></td>
<td>gt</td>
</tr>
<tr>
<td>Less than or equal</td>
<td><=</td>
<td>le</td>
</tr>
<tr>
<td>Greater than or equal</td>
<td>>=</td>
<td>ge</td>
</tr>
</table>
<pclass="caption">Figure 31 - comparison operators for numbers and strings</p>
<p>It may be worth mentioning that like other programming languages, the curly braces in an if statement enclosing the block of code are only really required if there is more than one statement to be executed, but it is good practice to include them anyway.</p>
<p>Perl also has a unique syntax for an if statement and that is the postfix conditional. In the previous example, we execute a single say statement if the condition evaluates to true. We can rewrite this as</p>
<pclass="inset">say 'true' if $x==1;</p>
<p>Note that we do not need the parentheses around the condition (although they can be included if required) and there are no curly braces. This syntax is only available when a single line of code is to be executed so we can’t include a code block.</p>
<p>Another shortcoming of the postfix conditional is that you cannot add else or elseif clauses as you can with a conventional if statement. It is a useful and easy to read syntax where you have just a single statement to be executed based on some condition.</p>
<h2class="sectiontitle">else and elsif</h2>
<p>Again, these are similar in Perl as in other programming languages. When we use a conditional statement to execute a block of code, let’s call that the true block since it is executed if the condition evaluates to true, we can add an else statement at the end which executes a second block of code if the condition is false. For obvious reasons, we might call that the false block.</p>
<p>Figure 32 shows an amended version of the conditional.pl script shown in figure 30, this time an else clause has been added.</p>
<preclass="inset">
1. #!/usr/bin/perl
2. # conditional.pl by Bill Weinman <http://bw.org/contact/>
3.
4. use 5.16.0;
5. use warnings;
6.
7. my $x = 23;
8. my $y = 1;
9.
10. if ($x==1){
11. say 'true';
12. } else {
13. say 'false';
14. }
15.
16. say "x is $x; y is $y";</pre>
<pclass="caption">Figure 32 - revised version of conditional.pl with an else clause added</p>
<p>In this case, we will output “true” if the condition evaluates to true (that is, if $x has a value of 1) or “false” if the condition evaluates to false.</p>
<p>Notice that there is no condition attached to the else clause. We are not testing the value of x again, we are simply executing the code based on the result of the initial comparison. However, we can check it again. Let’s say we want to output “Very true” if $x has a value of 2, “Absolutely true”, if $x has a value greater than 2 and “false” otherwise.</p>
<p>To do that, we need to add a couple of elsif clauses (note the spelling which will look strange if you are experienced with other programming languages). A combination of if, elsif and else clauses acts a little bit like a switch statement with else being analogous to the default clause. For obvious reasons, you would generally want this to be the last clause. Actually, I tried inserting an additional elsif clause after the else clause and this generated an error so it seems that the else clause (if there is one) must be last.</p>
<preclass="inset">
1. #!/usr/bin/perl
2. # conditional.pl by Bill Weinman <http://bw.org/contact/>
<pclass="caption">Figure 33 shows conditional.pl again, but this time, we have added a couple of elsif clauses between the initial if statement and the else clause. You will notice that an elsif clause is just another if statement, the only difference is that we are using the elsif statement rather than if. Otherwise, the syntax is identical.</p>
<p>A final point worth noting here are that we may need to be careful about logical gaps. The above program kind of makes sense when dealing with integers, but not so much if we are dealing with floats. For example, in the example in figure 33, there are four possible outcomes as follows:</p>
<preclass="inset">
Condition Output
x==1 True
x==2 Very true
x>2 Absolutely true
x evaluates to anything else False</pre>
<pclass="caption">Figure 34 - table of possible outputs from the version of conitional.pl shown in figure 33</p>
<p>The implication here is that the final clause, the else clause, executes if x is 0 or less. However, if x is, let’s say, 1.5, this is not covered by the if or either elsif clause so it would lead to an output of false. If x had a value of 2.5, it would be covered by the final elsif clause, so we have inconsistent logic. That is deliberate here, because it demonstrates the point that you sometimes need to be careful with data types which might break your logic. This is probably particularly important in Perl because of its duck typing.</p>
<h1class="sectiontitle">Negative Conditionals with Unless</h1>
<p>We could use a type of inverse conditional to test for a negative. For instance, if we want to execute some code if $x does not equal 1, the if statement would look like this.</p>
<pclass="inset">if ($x!=1) { ……</p>
<p>Note, if we make this change to the version of conditional.pl, we are sort of breaking the code because now, the output will either be true if x doesn’t equal 1 or false if it does. Since neither elsif clause tests to see if x is equal to 1, if it is, the else clause is executed. So in short, a value of 1 triggers the else clause since there are no matches with any of the conditions, anything else matches the first condition so the other two conditions are never evaluated.</p>
<p>That was a quick sidebar. The key point covered here is that we can also use a postfix operator for a negative condition. So, if we consider the condition with a negative, shown above, we can replace this with</p>
<pclass="inset">unless ($x==1)</p>
<p>This does exactly the same thing although many Perl programmers think this is a less elegant syntax so you probably won’t see it very often. As with if, unless also has a post fix syntax so we can say</p>
<pclass="inset">say 'true' unless ($x==1);</p>
<p>Again, this does the same thing, although in a form you won’t often see outside of Perl and this syntax is more popular with Perl programmers. Now, bear in mind that this code is equivalent to an if statement that executes some code if x does not equal one, we can also negate the condition here, again just as we did with the if statement, so that the code is executed if x does equal one. Effectively a double negative! This would give us</p>
<pclass="inset">unless ($x!=1)</p>
<p>using the conventional (prefix?) notation or </p>
<pclass="inset">say 'true' unless ($x!=1);</p>
<p>using the postfix notation.</p>
<h2class="sectiontitle">Switch with given and when</h2>
<p>There is no switch statement in Perl. Of course, it is possible to create the same behaviour using a sequence of if/elsif/else clauses where you can have as many elsif clauses as are required to ensure all possible cases are checked.</p>
<p>The point of a switch statement is to avoid having to code all these conditions so it would be a nice-to-have feature in Perl and, indeed, given and when is an attempt to implement a switch like syntax in Perl. However, it is still experimental and may never be fully developed and for this reason, if you include it in Perl code, you may see a lot of warning messages. In addition, since it is experimental, it should not be used in production code, partly because it is not entirely reliable, but mainly because it may change as it is further developed so any code you write with it may not work with future versions of Perl.</p>
<p>The syntax for given/when is shown in the code in figure 35.</p>
<p>The syntax is fairly similar to a conventional switch statements. The most obvious difference is that each case (introduced with the keyword when) has it’s own code-block that only executes if the when condition is met. This means that there is no need to use break statements and is therefore a little bit more intuitive than a switch statement. The other difference is that each when block is introduced with a conditional statement so there is no need to use a colon to separate each case from the accompanying code. This looks a little more conventional that a case statement and so is probably, again, a little but more intuitive since it is removing some of the extra syntax required by a switch statement.</p>
<p>There is a postfix version of when so we can rewrite each of the when clause as something like</p>
<pclass="inset">say ‘x’ when $x;</p>
<p>For obvious reasons, that is, because no condition is being specified, there is no postfix version of the default clause.</p>
<p>One reason why this type of syntax has never caught on with the Perl community is likely that there are better ways to accomplish the same thing. One of these is demonstrated in figure 36.</p>
<p>Here, we have created a hash with every possible value of $v. That is, the values we matched $v with in the when clauses of the given statement which were x, y and z.</p>
<p>The if statement on line 13 looks a little peculiar but it is testing whether the value given for $v matches any key in the hash. If it does, the code on line 14 outputs this value and the else clause is skipped.</p>
<p>If it doesn’t, the code in the else clause is executed so this is, in effect, our default clause.</p>
<p>This is probably a little bit more concise than a switch statement since you can easily extend it by adding extra key value pairs to the hash. Also, since Perl is optimised to search hashes so this method is probably at least as efficient and fast as a switch statement.</p>
<p>It’s probably worth pointing out that the code executed here is generic in the sense that the same line of code us executed, regardless of what the match with a key in the hash is. In that sense, it doesn’t seem to be very flexible.</p>
<p>I would be interested in trying to figure out how a block of code could be executed for each value in the hash but I suspect this will involve the series of if/elsif/else clauses a switch statement helps us to avoid but I will leave that until hashes have been covered in a little more detail.</p>
<p>However, it is possible that given/when may never be fully implemented in Perl so it is probably best to avoid it and use hashes as a lookup table instead.</p>
<p>The code in figure 37 shows a simple conditional operation.</p>
<preclass="inset">
1. #!/usr/bin/perl
2. # conditional.pl by Bill Weinman <http://bw.org/contact/>
3.
4. use 5.18.0;
5. use warnings;
6.
7. my $x = 1;
8. my $y = 1;
9.
10. if ( $x > $y ) {
11. say 'x is larger';
12. } else {
13. say "x is equal or smaller";
14. }</pre>
<pclass="caption">Figure 37 - ternary.pl which demonstrates a simple conditional operation</p>
<p>Here, we are creating variables $x and $y and using them in a conditional statement which will evaluate to true if $x is larger than $y and output an appropriate comment. If not, the comment in the else clause is output.</p>
<p>This can be rewritten as a ternary conditional operator and the rewritten code is shown in figure 38.</p>
<preclass="inset">
1. #!/usr/bin/perl
2. # conditional.pl by Bill Weinman <http://bw.org/contact/>
<p>This code does more or less the same thing as the example in figure 7 although it only displays x or y, depending on which is larger. Note that if they are the same, it will output y.</p>
<p>So, we have say with a conditional output which will output either the string ‘x’ or the string ‘y’. Whichever is output is then passed to say and is output to the screen.</p>
<p>The ternary conditional operator itself is quite simple and it could be described in very general terms as follows.</p>
<pclass="inset">condition ? true : false ;</p>
<p>We have a condition followed by a question mark. We then have a possible return value, a colon and a second possible return value (the statement is terminated with a semi-colon). If the condition evaluates to true, the first return value is returned. If it evaluates to false, the second return value is returned.</p>
<p>Since a ternary conditional operator returns a value, we can use a ternary conditional operator in place of one of the values in another ternary conditional operator, effectively nesting them. To demonstrate, note that the example shown in figure 38 returns the larger of x and y but will also return y if the two values are equal. If we want to return something else, let’s say ‘equal’ in such a case, we can use a ternary conditional operator that includes a condition that checks if they are equal and returns ‘equal’ if they are or the result of the original ternary conditional operator, the larger of x and y, if they are not. The rewritten (nested) ternary conditional operator would look like this.</p>
<p>This doesn’t work any differently without brackets but it emphasises the fact that the second value in the ternary conditional operator is a second ternary conditional operator so the meaning is a little bit clearer.</p>