| |||
Links Sections Statement Blocks and Local Variables Chapters Part I: Basic Perl 02-Numeric and String
Literals Part II: Intermediate Perl Part III: Advanced Perl 13-Handling Errors and
Signals Part IV: Perl and the Internet 21-Using Perl with Web
Servers Appendixes |
Statements can be very simple or very complex. The simplest statement is this
123;
which is a numeric literal followed by a semicolon. The
semicolon is very important. It tells Perl that the statement is complete. A
more complicated statement might be
$bookSize = ($numOfPages >= 1200 ? "Large" : "Normal");
which
says if the number of pages is 1,200 or greater, then assign "Large" to
$bookSize; otherwise, assign "Normal" to $bookSize.
Errata Note |
The printed version of this book showed the above example as $bookSize = ($numOfPages >= 1200 : "Large" : "Normal");. Please note that the first colon was a typographical error and it should be a question mark. David Rasch the sharp-eyed person that spotted this problem. |
In Perl, every statement has a value. In the first example, the value of the statement is 123. In the second example, the value of the statement could be either "Large" or "Normal" depending on the value of $numOfPages. The last value that is evaluated becomes the value for the statement.
Like human language in which you put statements together from parts of speech - nouns, verbs, and modifiers - you can also break down Perl statements into parts. The parts are the literals, variables, and functions you have already seen in the earlier chapters of this book.
Human language phrases - like, "walk the dog" - also have their counterparts in computer languages. The computer equivalent is an expression. Expressions are a sequence of literals, variables, and functions connected by one or more operators that evaluate to a single value - scalar or array. An expression can be promoted to a statement by adding a semicolon. This was done for the first example earlier. Simply adding a semicolon to the literal made it into a statement that Perl could execute.
Expressions may have side effects, also. Functions that are called can do things that are not immediately obvious (like setting global variables) or the pre- and post-increment operators can be used to change a variable's value.
Let's take a short diversion from our main discussion about statements and look at expressions in isolation. Then we'll return to statements to talk about statement blocks and statement modifiers.
Simple expressions consist of a single literal or variable. Table 6.1 shows some examples. Not much can be said about these expressions because they are so basic. It might be a matter for some debate whether or not an array or associative array variable can be considered a simple expression. My vote is yes, they can. The confusion might arise because of the notation used to describe an array or associative array. For example, an array can be specified as (12, 13, 14). You can see this specification as three literal values surrounded by parentheses or one array. I choose to see one array which fits the definition of a simple expression - a single variable.
Simple Expression | Description |
---|---|
123 | Integer literal |
Chocolate is great! | String literal |
(1, 2, 3) | Array literal |
$numPages | Variable |
Simple expressions with side effects are the next type of expression we'll examine. A side effect is when a variable's value is changed by the expression. Side effects can be caused using any of the unary operators: +, -, ++, --. These operators have the effect of changing the value of a variable just by the evaluation of the expression. No other Perl operators have this effect - other than the assignment operators, of course. Function calls can also have side effects - especially if local variables were not used and changes were made to global variables. Table 6.2 shows examples of different side effects.
Simple Expression | Description |
---|---|
$numPages++ | Increments a variable |
++$numPages | Increments a variable |
chop($firstVar) | Changes the value of $firstVar - a global variable |
sub firstsub { $firstVar = 10; } | Also changes $firstVar. |
Note that when the expressions $numPages++ and ++$numPages are evaluated, they have the same side effect even though they evaluate to different values. The first evaluates to $numPages, and the second evaluates to $numPages + 1. The side effect is to increment $numPages by 1.
The firstsub() function shown in Table 6.2 changes the value of the $firstVar variable, which has a global scope. This can also be considered a side effect, especially if $firstVar should have been declared as a local variable.
Simple expressions with operators are expressions that include one operator and two operands. Any of Perl's binary operators can be used in this type of expression. Table 6.3 shows a few examples of this type of expression.
Simple Expression | Description |
---|---|
10 + $firstVar | Adds ten to $firstVar |
$firstVar . "AAA" | Concatenates $firstVar and "AAA" |
"ABC" x 5 | Repeats "ABC" five times |
Another way of viewing 10 + $firstVar is as simple expression plus simple expression. Thus, you can say that a simple expression with an operator is defined as two simple expressions connected by an operator. When computer programmers define something in terms of itself, we call it recursion. Each time a recursion is done, the expression is broken down into simpler and simpler pieces until the computer can evaluate the pieces properly.
A complex expression can use any number of literals, variables, operators, and functions in any sequence. Table 6.4 shows some complex expressions.
Complex Expression |
---|
(10 + 2) + 20 / (5 ** 2) |
20 - (($numPages - 1) * 2) |
(($numPages++ / numChapters) * (1.5 / log(10)) + 6) |
There is an infinite number of expressions you can form with the Perl operator set. You can get extremely complicated in your use of operators and functions if you are not careful. I prefer to keep the expressions short, easy to document, and easy to maintain.
Tip |
Sometimes it is difficult to tell whether you have
enough closing parentheses for all of your opening parentheses. Starting
at the left, count each open parenthesis, and when you find a closing
parenthesis, subtract one from the total. If you reach zero at the end of
the expression, the parentheses are balanced. |
Now we'll go back to looking at statements.
Here is how I frequently use a statement block:
$firstVar = 10;
{
$secondVar >>= 2;
$secondVar++;
}
$thirdVar = 20;
The statement block serves to emphasize that the inner
code is set apart from the rest of the program. In this case, the initialization
of $secondVar is a bit more complex than the other variables. Using a
statement block does not change the program execution in any way; it simply is a
visual device to mark sections of code and a way to create local variables.
You can use the my() function to create variables whose scope is limited to the statement block. This technique is very useful for temporary variables that won't be needed elsewhere in your program. For example, you might have a complex statement that you'd like to break into smaller ones so that it's more understandable. Or you might want to insert some print statements to help debug a piece of code and need some temporary variables to accommodate the print statement.
Pseudocode |
Assign ten to $firstVar. Start the statement block. Create a local version of $firstVar with a value of A. Print $firstVar repeated five times. End the statement block. Print the global $firstVar. |
$firstVar = 10;
{
my($firstVar) = "A";
print $firstVar x 5 . "\n";
}
print("firstVar = $firstVar\n");
This program displays
AAAAA
firstVar = 10
You can see that the value of $firstVar has been
unchanged by the statement block even though a variable called
$firstVar is used inside it. This shows that the variable used inside
the statement block does indeed have a local scope.
Tip |
Statement blocks are also good to use when you
temporarily need to send debugging output to a file. Then, when all the
bugs have been found and the need for debugging is over, you can remove
the statement block quickly and easily because all the code is in one
spot. |
Statement Type | Description |
---|---|
No-action statements | These statements evaluate a value but perform no actions. |
Action statements | These statements perform some action. |
Assignment statements | These statements assign a value to one or more variables. They are discussed, along with the assignment operator, in Chapter 4, "Operators." |
Decision statements | These statements allow you to test a condition and choose among one or more actions. Decision statements are discussed in Chapter 7, "Control Statements." |
Jump statements | These statements let you unconditionally change the program flow to another point in your code. For instance, you could use the redo keyword to send your program flow back to the beginning of a statement block. Jump statements are discussed in Chapter 7, "Control Statements." |
Loop statements | These statements let you perform a series of statements repeatedly while some condition is true or until some condition is true. Loop statements are discussed in Chapter 7, "Control Statements." |
Modified Statements | These statements let you use the if, unless, until, and while keywords to change the behavior of a statement. |
Note |
A keyword is a word that is reserved for use
by Perl. These words (if, elsif, else,
while, unless, until, for,
foreach, last, next, redo, and
continue) are integral to the language and provide you with the
ability to control program flow. |
No-action statements are evaluated by Perl and have a value but perform no actions. For instance, the Perl statement 10 + 20; has a value of 30, but because no variables were changed, no work was done. The value of 20 is not stored anywhere, and it is quickly forgotten when the next statement is seen.
What good is a no-action statement if no work is done? A lot of Perl programmers use these simple statements as return values in functions. For instance:
sub firstSub {
doSomething();
condition == true ? "Success" : "Failure";
}
Because Perl returns the value of the last evaluated statement when
leaving a function, you can use no-action statements to let Perl know what value
should be returned to the main program. Notice that even though the ternary
operator was used, because there are no function calls or unary operators, no
work can be done.
Note |
I still like to use the return() function
to explicitly identify the return values. The previous example looks like
this when using the return() function:
sub firstSub { doSomething(); return(condition == true ? "Success" : "Failure"); } |
Modified statements use expressions in conjunction with a modifying keyword to perform some action. There are four modifying keywords: if, unless, until, and while. The basic syntax of a modified statement is
EXPRESSION modifier (CONDITION);
Let's look at some examples of
modified statements.
EXPRESSION if (CONDITION);
This is a compact way of saying
if (CONDITION) { EXPRESSION; }Let's prove that the if modifier works. Here's an example showing that the if modifier can prevent the evaluation of an expression.
Pseudocode |
Initialize the $firstVar and $secondVar variables to 20. Increment $firstVar if and only if $secondVar is equal to 10. Print the values of $firstVar and $secondVar. |
$firstVar = 20;
$secondVar = 20;
$firstVar++ if ($secondVar == 10);
print("firstVar = $firstVar\n");
print("secondVar = $secondVar\n");
This program prints
firstVar = 20
secondVar = 20
The program doesn't increment $firstVar because
the value of $secondVar is 20 at the time the condition is evaluated.
If you changed the 10 to a 20 in the condition, Perl would increment
$firstVar.
You can find out about the if statement - as opposed to the if modifier - in Chapter 7, "Control Statements."
Note |
The condition expression can be as complex as you'd
like. However, I believe that one of the goals of statement modifiers is
to make programs easier to read and understand. Therefore, I use modifiers
only with simple conditions. If complex conditions need to be met before
an expression should be evaluated, using the if statement is
probably a better idea. |
The unless modifier is the opposite of the if modifier. This modifier evaluates an expression unless a condition is true. The basic syntax of a modified statement with the unless modifier is
EXPRESSION unless (CONDITION);
This is a compact way of saying
if (! CONDITION) {
EXPRESSION;
}
This modifier helps to keep program code clearly understandable
because you don't have to use the logical not operator to change the
value of a condition so you can evaluate an expression. Let's look back at the
example from a moment ago.
Pseudocode |
Initialize the $firstVar and $secondVar variables to 20. Increment $firstVar unless $secondVar is equal to 10. Print the values of $firstVar and $secondVar. |
$firstVar = 20;
$secondVar = 20;
$firstVar++ unless ($secondVar == 10);
print("firstVar = $firstVar\n");
print("secondVar = $secondVar\n");
This program prints:
firstVar = 21
secondVar = 20
If you were limited to using only the if
modifier, the modified statement would read
$firstVar++ if ($secondVar != 10);
I feel that the unless
modifier is more direct. All things being equal, the concept of
$secondVar being equal to 10 is easier to grasp than the concept of
$secondVar not being equal to 10. Of course, this is a trivial example.
Let's look at something more substantial before we move on.
One of the drawbacks of associative arrays is that they quietly redefine the value of any key when that key is assigned a new value, thereby losing the old value. If you are reading from a list of key-valuepairs, this might not be the behavior you need. The unless modifier can be used to prevent element assignment if the key has already been used. Listing 6.1 shows the unless modifier used in a program.
Pseudocode |
Call the assignElement() function to create two elements in the @array associative array. Call the printArray() function. Try to redefine the value associated with the "A" key by calling assignElement(). Print the array again to verify that no elements have changed. |
Listing 6.1-06LST01.PL - Using the unless Modifier to Control Array Element Assignment |
|
This program displays
A = AAAA
B = BBBB
A = AAAA
B = BBBB
These lines of code should look a little familiar to you. The
while loop in the printArray() function was used in a Chapter
5 example. The assignElement() function will make an assignment unless
a key-value pair with the same key already exists. In that case, the assignment
statement is bypassed.
EXPRESSION until (CONDITION);
This is a compact way of saying
until (CONDITION) {
EXPRESSION;
}
The expression is evaluated only while the condition is false. If the
condition is true when the statement is encountered, the expression will never
be evaluated. The following example proves this:
Pseudocode |
Initialize $firstVar to 10. Repeatedly evaluate $firstVar++ until the condition $firstVar > 2 is true. Print the value of $firstVar. |
$firstVar = 10;
$firstVar++ until ($firstVar > 2);
print("firstVar = $firstVar\n");
This program displays
firstVar = 10
This shows that the expression $firstVar++
was never executed because the condition was true the first time it was
evaluated. If it had been executed, the value of $firstVar would have
been 11 when printed. In this case, the until modifier worked exactly
like the unless modifier.
However, when the condition is false for the first evaluation, Perl executes the expression repeatedly until the condition is true. Here is an example:
Pseudocode |
Initialize $firstVar to 10. Repeatedly evaluate $firstVar++ until the condition $firstVar > 20 is true. Print the value of $firstVar. |
$firstVar = 10;
$firstVar++ until ($firstVar > 20);
print("firstVar = $firstVar\n");
This program displays
firstVar = 21
In this case, the $firstVar++ expression is
executed 11 times. Each execution of the expression increments the value of
$firstVar. When $firstVar is equal to 21, the statement ends
because 21 is greater than 20, which means that the condition is true.
You can find out about the until statement - as opposed to the until modifier - in Chapter 7, "Control Statements."
EXPRESSION while (CONDITION);
This is a compact way of saying
while (CONDITION) {
EXPRESSION;
}
The expression is evaluated only while the condition is true. If the
condition is false when the statement is encountered, the expression will never
be evaluated. Here is an example using the while modifier.
Pseudocode |
Initialize $firstVar to 10. Repeatedly evaluate $firstVar++ while the condition $firstVar < 20 is true. Print the value of $firstVar. |
$firstVar = 10;
$firstVar++ while ($firstVar < 20);
print("firstVar = $firstVar\n");
This program displays
firstVar = 20
You can compare this example directly to the last example given for the until modifier. Because the until modifier is the opposite of the while modifier, the operators in the conditions are also opposite in nature.
You can find out about the while statement - as opposed to the while modifier - in Chapter 7, "Control Statements."
Next, you read about statement blocks. These program constructs are good to logically isolate one block of statements from the main program flow. You can also use statement blocks and the my() function to create local variables. This is mainly done for debugging reasons or to make small program changes that are guaranteed not to affect other portions of the program.
Then, seven types of statements were mentioned: no-action, action, assignment, decision, jump, loop, and modified. This chapter described no-action, action, and modified statements. Assignment statements were mentioned in Chapter 3, "Variables" and again in Chapter 4,"Operators" . Decision, jump, and loop statements are covered in Chapter 7,"Control Statements." .
Modified statements use the if, unless, until, and while keywords to affect the evaluation of an expression. The if keyword evaluates an expression if a given condition is true. The unless keyword does the opposite: the expression is evaluated if a given condition is false. The until keyword repeatedly evaluates an expression until the condition is true. The while keyword is the opposite of until so that it repeatedly evaluates an expression until the condition is false.
The next chapter, "Control Statements," explores the decision, jump, and loop statement in detail.
$firstVar = 10;
$secondVar = 20;
$firstVar += $secondVar++ if ($firstVar > 10);
print("firstVar = $firstVar\n");
print("secondVar = $secondVar\n");