Perl 2 - Control Structures

Reading: Deitel Chapter 3 (3.1 - 3.6)

In the last lecture we saw how to write a program to execute a series of commands. The perl interpreter starts at the beginning of the program, and executes the statements in order, until it reaches the end of the program.

Now we learn how to get our programs to make decisions based on the data available to them.


Comparisons

Let's review some expressions and see what they evaluate to


program 1
             33 == 33;             # true
              8 == 3 +3;           # false
              5 != 4;              # true

"Hello World" eq "Hello World"; # true "yes" eq "no"; # false "brazil" ne "Brazil"; # true

download

we can also compare variables:


program 2

$a == $a; # always true

$x = 5; $y = 10; $x == $y - 5; # true

download

other numeric comparisons:


program 3
      $x <  $y;   # less than
      $x >  $y;   # more than
      $x <= $y;   # less than or equal
      $x >= $y;   # more than or equal
      
download

other string comparisons:


program 4
      $x lt $y;   # alphabetically before
      $x gt $y;   # alphabetically after
      $x le $y;   # alphabetically before or equal
      $x ge $y;   # alphabetically after or equal
download

a common mistake is using the wrong comparison for the variable type; make sure 
ou use numberic comparisons for numbers and string comparisons for strings.

don't confuse the assignment operator = with the equality comparison ==

a very common mistake is to compare two strings using ==

In Perl, Truth is defined as follows:

  1. The string "0" is False.
  2. The empty string ("" or '') is False
  3. The empty list is False
  4. The undefined value is False (e.g. an uninitialized variable)
  5. A number is false if it converts to string "0".
  6. Everything else is True.


program 5
#!/usr/local/bin/perl -w
# logical_expressions.pl

$a; # FALSE (not yet defined) $a = 1; # TRUE $b = 0; # FALSE $c = ""; # FALSE $d = 'true'; # TRUE $e = 'false'; # TRUE (watch out! "false" is a nonempty string) $f = ' '; # TRUE (a single space is non-empty) $g = "\n"; # TRUE (a single newline is non-empty) @h = (); # FALSE array $i = 0.0; # FALSE (converts to string "0") $j = '0.0'; # TRUE (watch out! The string "0.0" is not the same as "0")

download

Truth and the Comparison Operations

  • If a comparison operation is true, it returns 1.
  • If a comparison operation is false, it returns undefined.


program 6
$a =  4 == 1+3;
print "The answer is $a","\n";
download

The answer is 1.


Conditional Execution

Imagine we want to write a simple blast output evaluation program, for determining if individual blast hits are better than some predetermined threshold:

We have a very simple algorithm, expressed in pseudocode as:

Step 1: IF blast e value is LESS THAN OR EQUAL TO 1e-50
             THEN this is a significant hit - notify user and carry on
	          to step 2

Step 2: Program is finished - notify user

This is how we express this in perl:

Using the if keyword


program 7
# the variable $expect should be
# set previously in this program

if ($expect < 1e-50) { print "Good match!\n"; }

# end of program print "Done!\n";

download

(This is just a fragment of a program - it will not do much on it's own as the assumption is this piece of code is embedded in a larger program)

The more general form of this is

if ( expression ) { statement1 , statement2 , statement3 , ... statementN }

the program above can also be written
program 8
print "Good match!\n" if $expect < 1e-50;
download

The more general form of this is

statement if test expression

The preceeding construct requires parentheses and a statement block {}

the second construct does not.

A statement block allows you to include multiple statements to be conditionally executed

Unless

This is the converse of if


program 9
unless ($expect < 1e-50) {
        print "Not good enough!\n";
}
download

which can also be written as:


program 10
print "Not good enough!\n" unless $expect < 1e-50;
download

The else keyword

Now imagine we want to program a slightly different algorithm.

Again, expressed in pseudocode :

Step 1:
IF blast e value is LESS THAN OR EQUAL TO 1e-50
  THEN this is a significant hit - notify user, and increment the
       count of good matches and carry on to step 2
  OTHERWISE
       this is not a significant hit according to our criteria.
       notify the user, and carry on to step 2
Step 2:
This is the end of the program. notify the user.


program 11
if ($expect < 1e-50) {
        print "Good match!\n";
        $good_matches++;
}
else {
        print "Expectation value does not meet threshold\n";
}

# end of program - notify user print "Done!\n";

download

If-elsif-else constructs

Let's put all the above into a complete program, and introduce a new construct, elsif


program 12
#!/usr/local/bin/perl
# evaluate_expect.pl - evalautes user provided expect scores

# get the expect value from the unix command line $expect = shift @ARGV;

# check the user has entered something if (!defined($expect)) { die("Usage: evaluate_expect.pl EXPECT-VALUE"); }

if ($expect < 1e-50) { print "Good match!\n"; $good_matches++; } elsif ($expect < 1e-20) { print "Reasonable match\n"; } elsif ($expect < 1e-4) { print "borderline match\n"; } else { print "poor match\n"; }

download

Flowcharts

As a visual aid, you can draw flow charts depicting decision points and flow of control through your program. Deitel has an extensive discussion of this in chapter 3. The parts about flow charts are not compulsory reading, some people find them useful ways to think about program flow.

                    /\
                   /  \
                  /    \
                 /  is  \           +-------+
                /   $e   \   YES    |       |
 START   ----> <    <     > ------> | Good  | ----------> END
                \ 1e-50  /          | Match |              ^
                 \  ?   /           +-------+              |
                  \    /                                   |
                   \  /                                    |
                    \/                                     |
                     |              +-----------+          |
                     |              | Doesn't   |          |
                     +------------> | meet      |----------+
                      NO            | threshold |
                                    +-----------+


Logical Operators


Boolean logic

We have already seen the and operator and the or operator.

Often the symbols && and || are used in place of and/or. these operators have higher precedence.

Once the truth can be determined, the remainder of the expression is not evaluated.

We can also use the not operator, or the higher precedence !

Conditional evaluation


program 13
if ( 1 == 1 && 2 == 1 ) { ..... }
download

the 2==1 part of the expression is never evaluated; it doesn't need to be.

This means we can write things like this


program 14
$expect >= 0 or die("logic error; expect = $expect is invalid");
download

So long as the $expect >= 0 expression evaluates to TRUE, the second part of the expression is not evaluated. If the first part evaluates to FALSE then the second expression is evaluated and the program dies with an error message.


Pattern Matching I

Pattern matching is covered in more detail in a future lecture.


program 15
$a = 'gatttccaa';
if ($a =~ /ttt/) {
        print "contains three t's" ;
}
if ($a =~ /gaattc/) {
        print "contains an EcoRI site" ;
}
download

here is another example:


program 16
#!/usr/local/bin/perl
# characterize_sequence.pl

print "Type in a sequence (all on one line):\n"; $sequence = <STDIN>; chomp $sequence;

$sequence = lc($sequence); # make sequence lowercase

if ($sequence =~ /n/) { print "sequence contain at least one gap\n"; } if ($sequence =~ /atg/) { print "sequence contains possible translation start\n"; } if ($sequence =~ /gaattc/) { print "sequence contains EcoRI site\n"; } print "Done!\n";

download


Nested ifs and indentation


program 17
# $test1 and $test2 are assumed to be set
# previously in the program

if ( $test1 ) { if ($test2) { print "test1 and test2 are both TRUE"; } else { print "test1 is TRUE and test2 is FALSE"; } } else { if ($test2) { print "test1 is FALSE and test2 is TRUE"; } else { print "test1 and test2 are both FALSE"; }

}

download


Exercises:

Write a script that divides two numbers entered by the user. it should check that the divisor is not zero to prevent a division by 0 error.

optional:

draw the following code as a flow chart


program 18
#!/usr/local/bin/perl
# pentagon.pl

print "Welcome to the Pentagon\n\n";

print "Please Enter your name:\n"; $name = <STDIN>; chomp $name;

print "Please Enter your password:\n"; $password = <STDIN>; chomp $password;

$authrorization_level = 0;

if ($name eq "") { print "You did not enter a name!\n"; print "Goodbye\n"; exit; }

# allow guest logins if ($name eq "guest") { $authorization_level = 1; }

# ordinary user logins if ($name eq "Tony Blair" && $password eq "Cherie") { $authorization_level = 2; }

# privileged user logins if ($name eq "George W Bush" && $password eq "DUBYA") { $authorization_level = 1000; }

if (!$authorization_level) { print "You are not authorized to use this system\n"; print "Goodbye!\n"; exit; }

print "You are an authorized user.\n"; print "Your security clearance level is $authorization_level.\n"; print "What do you want to do today, $name?\n";

$command = <STDIN>; chomp $command;

if ($command eq "start world war III") { if ($authorization_level >= 1000) { print "Certainly sir!\n"; # run the nuclear missle subroutine launch_nuclear_missiles(); print "Have a nice day!\n"; exit; } else { print "You are not authorized to $command\n"; exit; } }

download


Chris Mungall cjm@fruitfly.org
Berkeley Drosophila Genome Project