On Day 2, "Basic Operators and Control Flow," you learned about the following operators:
Today, you learn about the rest of the operators that Perl provides, as well as about operator associativity and precedence. The operators are
The arithmetic operators that you have seen so far-the +, -, *, and / operators-work the way you expect them to: They perform the operations of addition, subtraction, multiplication, and division.
Perl also supports three other arithmetic operations:
Although these operators aren't as intuitively obvious as the ones you've already seen, they are quite easy to use.
The exponentiation operator, **, provides a convenient way to multiply a number by itself repeatedly. For example, here is a simple Perl statement that uses the exponentiation operator:
$x = 2 ** 4;
The expression 2 ** 4 means "take four copies of two and multiply them." This statement assigns 16 to the scalar variable $x.
Note that the following statements are equivalent, but the first statement is much more concise:
$x = 2 ** 7; $x = 2 * 2 * 2 * 2 * 2 * 2 * 2;
When an exponentiation operator is employed, the base value (the value to the left of the **) is the number to be repeatedly multiplied. The number to the right, called the exponent, is the number of times the multiplication is to be performed. Here are some other simple examples of the exponentiation operator:
$x = 9 ** 2; # 9 squared, or 81 $x = 2 ** 3; # 2 * 2 * 2, or 8 $x = 43 ** 1; # this is just 43
The ** operator also works on the values stored in variables:
$x = $y ** 2;
Here, the value stored in $y is multiplied by itself, and the result is stored in $x. $y is not changed by this operation.
$x = 2 ** $y;
In this case, the value stored in $y becomes the exponent, and $x is assigned 2 multiplied by itself $y times.
You can use the exponent operator with non-integer or negative exponents:
2 ** -5 # this is the fraction 1/32 5 ** 2.5 # this is 25 * the square root of 5
Listing 4.1 shows an example of a simple program that uses the
exponential operator. It prompts for a number, $exponent,
and prints out 2 ** $exponent.
Listing 4.1. A program that prints out the powers of two.
1: #!/usr/local/bin/perl 2: 3: # this program asks for a number, n, and prints 2 to the 4: # exponent n 5: 6: print ("Enter the exponent to use:\n"); 7: $exponent = <STDIN>; 8: chop ($exponent); 9: print ("Two to the power $exponent is ", 10: 2 ** $exponent, "\n");
$ program4_1 Enter the exponent to use: 16 Two to the power 16 is 65536 $
The program shown in Listing 4.1 is useful
if you have to use, or be aware of, numbers such as 4,294,967,295
(the largest number that can be stored in a 32-bit unsigned integer)
and 2,147,483,647 (the largest number that can be stored in a
32-bit signed integer). The former is equivalent to 2
** 32 - 1, and the latter is equivalent to 2
** 31 - 1
DON'T use the exponent operator with a negative base and a non-integer exponent: (-5) ** 2.5 # error The result of this expression is a complex (non-real) number (just as, for instance, the square root of -2 is a complex number). Perl does not understand complex numbers. DON'T produce a result that is larger than the largest floating-point number your machine can understand: 10 ** 999999 # error In this example, the exponent is too large to be stored on most machines. |
The remainder operator retrieves the remainder resulting from the division of one integer by another. Consider the following simple example:
$x = 25 % 4;
In this case, 25 divided by 4 yields 6, with a remainder of 1. The remainder, 1, is assigned to $x.
The % operator does not work on values that are not integers. Non-integers are converted to integers, as follows:
$x = 24.77 % 4.21; # same as 25 % 4
Because division by 0 is impossible, you can't put a 0 to the right of a % operator.
$x = 25 % 0; # error: can't divide by 0 $x = 25 % 0.1; # error: 0.1 is converted to 0
The unary negation operator is a - character in front of a single value. (This distinguishes it from the subtraction operator, which appears between two values.) It is equivalent to multiplying the value by -1, as illustrated by this example:
- 5; # identical to the integer -5 - $y; # equivalent to $y * -1
On Day 2, "Basic Operators and Control Flow," you learned about the equality comparison operator (==), which compares two values and tests whether they are equal.
$x = $a == $b;
Recall that the value of $x depends on the values stored in $a and $b:
The == operator is an example of a comparison operator. Comparison operators are most commonly used in control statements such as the if statement, as follows:
if ($a == $b) { print("$a is equal to $b\n"); }
In Perl, the comparison operators are divided into two classes:
Table 4.1 defines the integer-comparison operators available in
Perl.
Operator | Description |
< | Less than |
> | Greater than |
== | Equal to |
<= | Less than or equal to |
>= | Greater than or equal to |
!= | Not equal to |
<=> | Comparison returning 1, 0, or -1 |
Here are simple examples of each of the first six operators in Table 4.1:
$x < 10 # true if the value of $x is less than 10 $x > 10 # true if $x is greater than 10 $x == 10 # true if $x is equal to 10 $x <= 10 # true if $x is less than or equal to 10 $x >= 10 # true if $x is greater than or equal to 10 $x != 10 # true if $x is not equal to 10
Each of these operators yields one of two values:
The <=> operator is a special case. Unlike the other integer comparison operators, <=> returns one of three values:
For example, consider the following statement:
$y = $x <=> 10;
These are the possible results:
In any given statement, it's best to use the comparison that can be most easily read. For example, consider the following:
if (3.2 < $x) { # conditionally executed stuff goes here }
Although the expression 3.2 < $x< is perfectly valid, it isn't easy to read because variables usually appear first in comparisons. Instead, it would be better to use
if ($x >= 3.2) { ...
because this is easier to understand. I'm not sure exactly why this is true; I think it's related to the way the English language is spoken. (Normally, we say, "If I had five dollars, I'd buy some milk," instead of, "If five dollars had I, I'd buy some milk," even though both are correct.)
For every numeric-comparison operator, Perl defines an equivalent
string-comparison operator. Table 4.2 displays each string-comparison
operator, the comparison it performs, and the equivalent numeric-comparison
operator.
String operator | Comparison operation | Equivalent numeric operator |
lt | Less than | < |
gt | Greater than | > |
eq | Equal to | == |
le | Less than or equal to | <= |
ge | Greater than or equal to | >= |
ne | Not equal to | != |
cmp | Compare, returning 1, 0, or -1 | <=> |
Perl compares strings by determining their places in an alphabetical order. For example, the string aaa is less than the string bbb, because aaa appears before bbb when they are sorted alphabetically.
Here are some examples of string-comparison operators in action:
$result = "aaa" lt "bbb"; # result is true $result = "aaa" gt "bbb"; # result is false $result = "aaa" eq "bbb"; # result is false $result = "aaa" le "aaa"; # result is true $result = "aaa" ge "bbb"; # result is false $result = "aaa" ne "aaa"; # result is false $result = "aaa" cmp "bbb"; # result is -1
If you are familiar with the C programming language, you might have noticed that the behavior of the cmp operator is identical to that of the C function strcmp().
You might be thinking: If strings and integers are equivalent in Perl, why do we need two kinds of comparison operators?
To answer this, consider the strings 123 and 45. The result when these two strings are compared depends on whether a string or integer comparison is being performed.
$result = "123" < "45"; $result = "123" lt "45";
In the first statement, the strings 123 and 45 are converted to integers, and 123 is compared to 45. The result is false and $result is assigned 0, because 123 is not less than 45.
In the second statement, 123 is alphabetically compared to 45. Because 123 is alphabetically less than 45, the result in this case is true, and $result is assigned a nonzero value.
Because these results are different, you must ensure that you are using the proper comparison operator every time. If you don't, your program can contain errors that are not easy to spot. For instance, consider the following:
$var1 = "string 1"; $var2 = "string 2"; $result = $var1 == $var2; # this statement is bad
Because == is a numeric-comparison operator, the values string 1 and string 2 are converted to integers before the comparison is performed. Because both strings are non-numeric, they are both converted to the integer 0, and the following comparison becomes true:
$var1 == $var2
This is probably not what you want.
There is one thing to keep in mind when you use comparison operators: Floating-point numbers don't always behave properly in comparisons.
Take a look at Listing 4.2.
Listing 4.2. A program that contains a floating-point comparison.
1: #!/usr/local/bin/perl 2: 3: $value1 = 14.3; 4: $value2 = 100 + 14.3 - 100; 5: if ($value1 == $value2) { 6: print("value 1 equals value 2\n"); 7: } else { 8: print("value 1 does not equal value 2\n"); 9: }
$ program4_2 value 1 does not equal value 2 $
At first glance, you might think that $value1 and $value2 are identical. However, when you run this program, you get the following:
value 1 does not equal value 2
What is wrong? To find out, print out the values of $value1 and $value2 before doing the comparison.
#!/usr/local/bin/perl $value1 = 14.3; $value2 = 100 + 14.3 - 100; print("value 1 is $value1, value2 is $value2\n"); if ($value1 == $value2) { print("value 1 equals value 2\n"); } else { print("value 1 does not equal value 2\n"); }
When you run this program, you get the following output:
value 1 is 14.300000000000001, value 2 is 14.299999999999997 value 1 does not equal value 2
Well, Perl isn't lying: $value1 and $value2 are different. What happened?
To understand what's going on, consider what happens when you take an ordinary calculator and tell it to divide 8 by 3. The actual answer is
2.6666666...
with the number of 6s being infinite. Because your calculator can't display an infinite number of 6s, what it displays is something like the following:
2.6666666667
This is as close to the actual number as your calculator can get. The difference between the actual number and the number displayed is an example of a round-off error.
Round-off errors often occur when Perl (or almost any other programming language) stores a floating-point number or adds a number to a floating-point number. The statement
$value1 = 14.3;
actually assigns
14.300000000000001
to $value1, because 14.3 cannot be exactly represented in the machine's floating-point storage. When 100 is added to this number and subtracted again, the result is
14.299999999999997
Note that both numbers are very close to 14.3 but aren't exactly 14.3 due to round-off errors. What's worse, each number is affected by a different set of round-off errors, so the two numbers are not identical.
The moral of the story? Be very careful when you use floating-point numbers in comparisons, because round-off errors might affect your results.
The comparison operators you've seen so far are sufficient if you need to test for only one condition before executing a particular code segment, as in this example:
if ($value == 26) { # the code to execute if the condition is true }
Suppose, however, that a particular section of code is to be executed only when a variety of conditions are true. You can use a sequence of if statements to test for the conditions, as follows:
if ($value1 == 26) { if ($value2 > 0) { if ($string1 eq "ready") { print("all three conditions are true!\n"); } } }
This is tiresome to write and not particularly easy to read.
Fortunately, Perl provides an easier way to deal with multiple conditions: the logical operators. The following logical operators are defined:
$a || $b # logical or: true if either is nonzero $a && $b # logical and: true only if both are nonzero ! $a # logical not: true if $a is zero
Perl 5 also defines these logical operators:
$a or $b # another form of logical or $a and $b # another form of logical and not $a # another form of logical not $a xor $b # logical xor: true if either $a or $b is nonzero, but not both
The or, and, and not operators listed are identical to ||, &&, and !, except that their precedence is lower. (Operator precedence determines the order in which operators are evaluated, and is discussed later today.)
In each case, the result of the operation performed by a logical operator is nonzero if true and 0 if false.
$a = 5; $b = 0; $a || $b; # true: $a is not zero $b || $a; # also true $a && $b; # false: $b is zero ! $a; # false: $a is nonzero, so ! $a is zero ! $b; # true: $b is zero, so ! $b is nonzero
These logical operators enable you to test for multiple conditions more conveniently. Instead of writing, for example, this code:
if ($value1 == 26) { if ($value2 > 0) { if ($string1 eq "ready") { print("all three conditions are true!\n"); } } }
you now can write this code instead:
if ($value == 26 && $value2 > 0 && $string1 eq "ready") { print("all three conditions are true!\n"); }
In each case, the result is the same: the print operation is performed only when $value is 26, $value2 is greater than 0, and $string1 is "ready."
When Perl sees a logical AND operator or a logical OR operator, the expression on the left side of the operator is always evaluated first. For example, consider the following:
$a = 0; $b = 106; $result = $a && $b;
When Perl is evaluating the expression $a && $b, it first checks whether $a is 0. If $a is 0, $a && $b must be false regardless of the value of $b, so Perl doesn't bother checking the value of $b. (This is called short-circuit evaluation.)
Similarly, in the following example, Perl doesn't bother checking $b, because $a is nonzero and therefore $a || $b must be true:
$a = 43; $b = 11; $result = $a || $b;
You can take advantage of the order of evaluation of expressions in || or && to safeguard your code.
$x == 0 || $y / $x > 5
Here is how the preceding statement protects you from division-by-zero errors:
Expressions that contain logical operators can be contained in larger expressions. The following is an example:
$myval = $a || $b || $c;
Here, Perl evaluates the expression $a || $b || $c and assigns its value to $myval.
To understand the behavior of this statement, recall that the || operator evaluates its subexpressions in the order given, and evaluates a subexpression only if the previous subexpression is zero. This means that $b is evaluated only if $a is zero.
When the logical OR operator is used in a larger expression, its value is the last subexpression actually evaluated, which is the first subexpression of the logical OR operator that is nonzero. This means that
$myval = $a || $b || $c;
is equivalent to
if ($a != 0) { $myvalue = $a; } elsif ($b != 0) { $myvalue = $b; } else { $myvalue = $c; }
The logical AND operator works in the same way, but isn't as useful. The statement
$myval = $a && $b && $c;
is equivalent to
if ($a == 0) { $myvalue = $a; } elsif ($b == 0) { $myvalue = $b; } else { $myvalue = $c; }
This means that $myval is set to either 0 or the value of $c.
Perl enables you to manipulate the binary digits (or bits) of an integer. To understand how Perl does this, first look at what a bit is and how computers store integers. Once you understand how bits work, you can easily figure out how the bit-manipulation operators work. (If you are familiar with binary notation and the computer representation of an integer, feel free to skip the following section.)
On Day 3, "Understanding Scalar Values," you learned that Perl understands three different notations for integers:
However, when a computer stores an integer, it uses none of these notations; instead, it uses base 2, or binary notation.
In binary notation, every number is represented as a series of 0s and 1s. For instance, the number 124 is represented as
01111100
To understand how to get from base-10 notation to binary notation, recall what the number 124 represents. When we write "124," what we really mean is the following:
In grade school, your teacher probably said these digits represented the "ones place," the "tens place," and the "hundreds place." Each "place" is ten times larger than the place to its right. This means that you also can think of 124 as follows:
In binary notation, you can use this same method, but replace the 10s with 2s. Here's how to use this method to figure out that the binary number 01111100 is equivalent to 124 in standard notation. Starting from the right, you have:
Adding 2, 8, 16, 32, and 64 gives you 124.
Each of the 0s and 1s in the binary number 01111100 is called a bit (which is short for binary digit). Each bit can have only two possible values: 0 or 1.
In computers, integers are stored as a sequence of bits. This sequence of bits is normally 8, 16, or 32 bits long, depending on the size and configuration of your computer. In the examples in today's lesson, 8-bit integers are assumed; to convert an 8-bit binary number to a 16-bit binary number, just add eight zeros to the left. For example, the following numbers are equivalent:
01111100 # 124 as an 8-bit integer 0000000001111100 # 124 as a 16-bit integer
The examples in today's lesson use 8-bit integers. The Perl bitwise operators will work on integers of any size.
The following bit-manipulation operators are supported in Perl:
In Perl, the & operator represents the bitwise AND operation. This operation works as follows:
This might sound complicated, but when you take a look at an example, you'll see that it's pretty easy to figure out. For instance, consider the following:
$result = 124.3 & 99;
First, the left operand, 124.3, is converted to an integer, becoming 124. (The right operand, 99, does not need to be converted.) Next, take a look at the binary representations of 124 and 99:
01111100 # this is 124 in binary 01100011 # this is 99 in binary
When you examine each pair of bits in turn, you can see that only the second and third pairs (from the left) are both 1. Thus, the & operation yields the following binary result:
01100000
This is 96 in standard notation. As a consequence, the statement
$result = 124.3 & 99;
assigns 96 to $result.
DO use the & operator with strings, provided the strings can be converted to numbers, as follows: $result = "124.3" & "99"; Remember: Strings and integers are interchangeable in Perl. DON'T confuse the & operator with the && operator. The && operator performs a logical AND operation, not a bitwise AND operation. For example, the statement $result = 124.3 && 99; assigns a nonzero value to $result (because 124.3 and 99 are both nonzero). This nonzero value is not likely to be the result you want. DON'T use the & operator with negative integers, because Perl will convert them to unsigned integers, and you won't get the result you want. |
The bitwise OR operator, |, also compares two integers one bit at a time. However, in the bitwise OR operation, a result bit is 1 if either of the corresponding bits in the operands is 1.
To see how this works, look at another example:
$result = 124.3 | 99;
Here's how this operation is performed:
01111100 01100011
In this example, every bit becomes 1 except the first one, because at least one of each of the other pairs is a 1. Therefore, the result is
01111111
which translates to 127. This means that the following statement assigns 127 to $result:
$result = 124.3 | 99;
DO make sure you are using the proper bitwise operator. It's easy to slip and assume you want bitwise OR when you really want bitwise AND. (Trust me.) DON'T confuse the | operator (bitwise OR) with the || operator (logical OR). |
The bitwise XOR ("exclusive or") operator, ^, is similar to the bitwise OR operator, but it's a little more demanding. In the bitwise OR operation, a result bit is 1 if either of the corresponding bits in the operands is 1. In the bitwise XOR operation, a result bit is 1 if exactly one of the corresponding bits in the operands is 1.
Here is an example of the bitwise XOR operation:
$result = 124.3 ^ 99;
This works as follows:
01111100 # this is 124 01100011 # this is 99
In this case, the result is
00011111
which is 31. To work through how you get this result, consider the following:
From this, you can determine that the following statement assigns 31 to $result:
$result = 124.3 ^ 99;
Unlike the other bitwise operators you've seen so far, the bitwise NOT operator, ~, is a unary operator, meaning it works on only one operand.
The way it works is straightforward, as follows:
For example, consider the following:
$result = ~99;
The binary representation of 99 is
01100011
Applying the bitwise NOT operation to this number produces
10011100
This number, in standard notation, is 156. Therefore, the following statement assigns 156 to $result:
$result = ~99;
Note that the number of bits used to store an integer affects the results produced by the ~ operator. For example, if integers are stored in 16 bits on your computer, the number 99 is represented as
0000000001100011
This means that applying ~ to this number yields
1111111110011100
which is 65436 in standard notation. As a consequence, the statement
$result = ~99;
assigns 65436, not 156, to $result. (On a computer with 32-bit integers, the value assigned is 4294967196.)
Perl enables you to shift the bits of an integer using the << (shift left) and >> (shift right) operators. For example, in the statement
$result = $x >> 1;
every bit of the value stored in $x is shifted one place to the right, and the result is assigned to $result ($x itself is not changed).
To see how this works, consider the following example:
$result = 99 >> 1;
As you saw earlier, the binary representation of 99 is
01100011
Shifting every bit right one place yields
00110001
Note that a 0 is added at the far left, and the bit at the far right disappears.
Because 00110001 in binary notation is the same as 49 in standard notation, the following statement assigns 49 to $result:
$result = 99 >> 1;
The <<, or shift-left, operator works in the same way:
$result = 99 << 1;
The shift-left operator works as follows:
01100011 # the binary representation of 99 11000110 # after shifting left 1 bit
The result of the shift is 198, which is assigned to $result.
DO remember that when you use the >> operator, the bits on the right are lost. For example: $result1 = 17 >> 1; In this case, $result1 and $result2 are the same value, 8. This is because the rightmost bit is shifted out in both cases. DON'T shift left too far, or you might not get the result you want. For example, if you are using 16-bit integers, the statement $result = 35000 << 1; does not assign 70000 to $result as you might think it would because the largest value that can be stored in a 16-bit integer is 65536. |
In the following statement, the variable $result is assigned the value 49:
$result = 99 / 2;
Take a look at the binary representations of 99 and 49:
01100011 # 99 in binary form 00110001 # 49 in binary form
As you can see, dividing by 2 is identical to shifting right one bit-in each case, every bit is moved one place to the right. Similarly, shifting right two bits is equivalent to dividing by 4:
$result = 99 / 4; # $result is assigned 24 01100011 # 99 in binary 00011000 # 24 in binary
Multiplying by 4 is similar to shifting left two bits:
$result = 17 * 4; # $result is assigned 68 00010001 # 17 in binary 01000100 # 68 in binary
The general rules are as follows:
In the early days of programming, many programmers used shift operators in place of multiplication and division wherever possible, because the shift operations were usually more efficient. (In fact, some compilers would optimize their code by converting multiplication and division to shifts.) Today, it's usually best to use the shift operators when you are manipulating bits, and to use the multiplication and division operators when you're actually doing arithmetic. This will make your programs easier to understand.
As you saw on Day 2, the assignment operator = associates, or assigns, a value to a variable. For example, the statement
$result = 42;
assigns the value 42 to the variable $result.
The = operator can appear more than once in a single statement. For example, in the statement
$value1 = $value2 = "a string";
the character string a string is assigned to both $value1 and $value2.
Perl also supports other assignment operators, each of which combines an assignment with another operation. For example, suppose that you want to add a value to a scalar variable and assign the result to the following variable:
$var = $var + 1;
Another way to write this is with the += assignment operator:
$var += 1;
This statement adds the value 1 to the existing value of $var.
An assignment operator exists for just about every bitwise operator
and arithmetic operator that Perl supports. Table 4.3 lists the
assignment operators supported in Perl.
Operator | Operations performed |
= | Assignment only |
+= | Addition and assignment |
-= | Subtraction and assignment |
*= | Multiplication and assignment |
/= | Division and assignment |
%= | Remainder and assignment |
**= | Exponentiation and assignment |
&= | Bitwise AND and assignment |
|= | Bitwise OR and assignment |
^= | Bitwise XOR and assignment |
Table 4.4 shows examples of the assignment operators, along with
equivalent statements that use operators you've seen earlier.
Statement using | Equivalent Perl assignment operator statement |
$a = 1; | none (basic assignment) |
$a -= 1; | $a = $a - 1; |
$a *= 2; | $a = $a * 2; |
$a /= 2; | $a = $a / 2; |
$a %= 2; | $a = $a % 2; |
$a **= 2; | $a = $a ** 2; |
$a &= 2; | $a = $a & 2; |
$a |= 2; | $a = $a | 2; |
$a ^= 2; | $a = $a ^ 2; |
Any expression that contains an assignment operator can appear on the left side of another assignment operator. The following is an example:
($a = $b) += 3;
In cases such as this, the assignment enclosed in parentheses is performed first. This assignment is then treated as a separate subexpression whose value is the variable to which it is being assigned. For example, $a = $b has the value $a.
This means that the statement shown previously is equivalent to the following two statements:
$a = $b; $a += 3;
TIP |
Don't use assignments in this way unless you absolutely have to. At first glance, the statement appears to add 3 to $b as well as to $a. |
So far, you've seen two ways to add 1 to a scalar variable:
$a = $a + 1; $a += 1;
The first method uses the standard assignment operator = and the addition operator +, and the second method uses the addition assignment operator +=.
Perl also supports a third method of adding 1 to a scalar variable: the autoincrement operator, or ++. Here are some examples of the ++ operator in action:
$a++; ++$a; $result = $a++; $result2 = ++$a;
In each case, the ++ operator tells Perl to add 1 to the value stored in $a.
In some of the examples, the ++ is in front of the variable it is affecting, whereas in others the ++ follows the variable. If the ++ is first, the operation is a pre-increment operation; if the ++ follows, the operation is a post-increment operation.
To understand how the pre-increment operation works, first recall that you can use a single statement to assign a value to more than one variable, as follows:
$var1 = 43; $var2 = $var1 += 1;
Here, the original value stored in $var1, 43, has 1 added to it. The result, 44, becomes the new value of $var1. This new value of 44 is then assigned to $var2.
The pre-increment operation works in the same way:
$var1 = 43; $var2 = ++$var1;
The following code fragment tells Perl to add 1 to $var1 before doing anything else:
++$var1
As a result, $var1 becomes 44 before the value of $var1 is assigned to $var2. Therefore, $var2 is assigned 44.
The ++ operator is most frequently used in while statements. Listing 4.3 provides an example of a simple program that uses the ++ operator in a while statement.
Listing 4.3. A program that uses the pre-increment operation.
1: #!/usr/local/bin/perl 2: $value = 0; 3: while (++$value <= 5) { 4: print("value is now $value\n"); 5: } 6: print("all done\n");
$ program4_3 value is now 1 value is now 2 value is now 3 value is now 4 value is now 5 all done $
Note that the pre-increment operation enables you to add 1 to $value and test it all at the same time. This means that you no longer have to remember to add the following:
$value = $value + 1;
at the bottom of the while statement, which means that you are less likely to write a while statement that goes on forever.
Now see what happens when you change
while (++$value <= 5) {
to this:
while (++$value <= 0) {
and then run the program again. This time, you get the following:
all done
Because the ++ operator is in front of $value, 1 is added to $value before testing. This means that $value is not less than or equal to 0 when the while statement is executed for the first time; as a result, the code inside the while statement is never executed.
The post-increment operator also adds 1 to the variable with which it is associated. However, its behavior is slightly different:
$var1 = 43; $var2 = $var1++;
When the ++ operator appears after the variable, the ++ operator is performed after every- thing else is finished. This means that the original value of $var1, 43, is assigned to $var2. After this assignment is completed, 1 is added to $var1 and the new value of $var1 becomes 44.
To see how this works in while statements, examine Listing 4.4. Although it is similar to Listing 4.3, it performs a post-increment operation instead of a pre-increment operation.
Listing 4.4. A program that uses the post-increment operation.
1: #!/usr/local/bin/perl 2: $value = 0; 3: while ($value++ <= 5) { 4: print("value is now $value\n"); 5: } 6: print("all done\n");
$ program4_4 value is now 1 value is now 2 value is now 3 value is now 4 value is now 5 value is now 6 all done $
You are probably wondering why the output of Listing 4.4 contained the following line:
value is now 6
To figure out what happened, examine the value stored in $value
each time the condition in the while
statement is tested. Table 4.5 lists the contents of $value
when the condition is tested, the result of the test, and $value
immediately after the condition is tested (after the ++
operator is applied).
As you know, when the condition at the top of a while statement is true, the code inside the statement is executed, which in this case is
print("value is now $value\n");
This is why the line
value is now 6
appears-$value is 5 at the time the condition is tested, so the result is true.
To fix this problem, change the while condition to the following and run the program again:
while ($value < 5) {
This is the output you get from the changed program:
value is now 1 value is now 2 value is now 3 value is now 4 value is now 5 all done
Now, when $value is 5, the statement
while ($value++ < 5)
is false, and the code inside the while is not executed.
As you've seen, the ++ operator adds 1 to the value of the variable it is associated with and can appear either before or after the variable. The -- operator, or autodecrement operator, works in the same way, but it subtracts 1 from the value of the variable it is associated with, as follows:
$a--; --$a; $result = $a--; $result2 = --$a;
When the -- operator is in front of the variable, the operation is a pre-decrement operation, which means that 1 is subtracted from the variable before anything else happens.
$var1 = 56; $var2 = --$var1;
This subtracts 1 from $var1 and assigns the result, 55, back to $var1. The value 55 is then assigned to $var2.
When the -- operator follows the variable, the operation is a post-decrement operation, which means that 1 is subtracted from the variable after everything else happens.
$var1 = 56; $var2 = $var1--;
This assigns 56 to $var2
and then subtracts 1 from $var1,
which means that $var1
now has the value 55.
DO be careful when you use the autoincrement and autodecrement operators. As you've seen, it's easy to get confused and tell your program to loop one too many times or one too few. I tend not to use these operators in while statements except in very simple cases, because they can get confusing. A better solution is to use the for statement, which you'll learn about on Day 8, "More Control Structures." DON'T use ++ or -- on both sides of a single variable, as in this statement, because it isn't allowed in Perl: ++$var1--; DON'T use autoincrement or autodecrement on a variable and then use the variable again in the same statement. $var1 = 10; Is $var2 now 20, 21, or 22? It's impossible to tell. Even different versions of Perl can produce different results! |
If a string value contains only alphabetic characters, the ++ operator can be used to "add one" to a string. In other words, the operator replaces the last character of the string with the next letter of the alphabet. The following is an example:
$stringvar = "abc"; $stringvar++;
Here, $stringvar now contains abd.
Note that this works only with ++, not --:
$stringvar = "abc"; $stringvar--;
The -- operator treats abc as a number, which means that it is equivalent to 0. The resulting value of $stringvar is, therefore, -1.
Auto-incrementing strings using ++ also works on capital letters.
$stringvar = "aBC"; $stringvar++;
The value stored in $stringvar is now aBD.
If the last letter of the string is z or Z, ++ converts this letter to a or A, and then "adds one" to the second-to-last character of the string:
$stringvar = "abz"; $stringvar++; # $stringvar now contains "aca" $stringvar = "AGZZZ"; $stringvar++; # $stringvar now contains "AHAAA"
This also works if the string contains one or more trailing digits.
$stringvar = "ab4"; $stringvar++; # $stringvar now contains "ab5"
As in numeric operations, incrementing a string that ends in 9 carries over to the next character of the string. This works regardless of whether the next character is a digit or alphabetic character.
$stringvar = "bc999"; $stringvar++; # $stringvar now contains "bd000"
Incrementing string values using ++ works only if the variable has not already been converted to a number. $stringvar = "abc"; Here, the value of $stringvar is 6 because abc is converted to 0 by the += operator in the second statement. Also note that this does not work if the string value contains any character other than a letter or digit, or if a digit is located in the middle of the string. $stringvar = "ab*c"; In both of these cases, the value stored in $stringvar is converted to its numeric equivalent, 0, before the ++ operation is performed. This means that $stringvar is assigned the value 1. |
So far, the Perl operators you've seen operate only on integers. (To be exact, they can also operate on strings, but they convert the strings to integers first.) Perl also supports the following special operators that manipulate strings:
The string-concatenation operator, ., joins two strings together. For example, the following statement assigns the string potatohead to $newstring:
$newstring = "potato" . "head";
You can use the . operator with variables as in this example:
$string1 = "potato"; $string2 = "head"; $newstring = $string1 . $string2;
This also assigns potatohead to $newstring. Note that the values of $string1 and $string2 are not changed by the . operator: $string1 still has the value potato, and $string2 still has the value head.
The string-repetition operator, x (literally the letter x), makes multiple copies of a string and joins the copies together, as shown in this example:
$newstring = "t" x 5;
This statement takes five copies of the string t and joins them together, producing the string ttttt. This string is then assigned to the variable $newstring.
You can use variables as operands for the x operator, if you like, as follows:
$copystring = "t"; $repeats = 5; $newstring = $copystring x $repeats;
The only restriction is that the variable on the right of the
x must contain an integer
or a value that can be converted to an integer.
DO make sure you leave a space between the x operator and the values or variables on either side: $newstring = $oldstring x 5; # this is correct Normally, you don't need to put spaces between an operator and its operands. $x = $x + 1; # this is OK You need spaces around the x because the letter x can appear in variable names. (For example, $oldstringx is a perfectly valid variable name.) |
The .= operator combines the operations of string concatenation and assignment. For example, the following statements:
$a = "be"; $a .= "witched"; # $a is now "bewitched"
are equivalent to these statements:
$a = "be"; $a = $a . "witched";
You can use the .= operator to write a very simple program that reads multiple lines of input and joins them into a single string. This program is shown in Listing 4.5.
Listing 4.5. A program that reads input lines and concatenates them.
1: #!/usr/local/bin/perl 2: $resultstring = ""; 3: print("Enter your input - type an empty line to quit\n"); 4: $input = <STDIN>; 5: chop ($input); 6: while ($input ne "") { 7: $resultstring .= $input; 8: $input = <STDIN>; 9: chop ($input); 10: } 11: print ("Here is the final string:\n"); 12: print ("$resultstring\n");
$ program4_5 Enter your input - type an empty line to quit this is a test Here is the final string: thisisatest $
As you can see from the output of Listing 4.5, the four input lines are joined and have become a single string.
Note that there is a much simpler way to do this in Perl: using the built-in function join(). You'll learn about join() on Day 5, "Lists and Array Variables."
Perl also supports two other operators that do not fit into any of the preceding categories:
The comma operator (,) is an operator borrowed from the C programming language. It guarantees that a particular part of an expression (the part before the ,) is evaluated first.
Here is an example of a simple statement that uses the , operator:
$var1 += 1, $var2 = $var1;
Because the , operator indicates that the left operand is to be performed first, 1 is added to $var1 before $var1 is assigned to $var2. In effect, the , operator breaks a statement into two separate statements, as follows:
$var1 += 1; $var2 = $var1;
In fact, the only real reason to use the , operator is when two operations are so closely tied together that it is easier to understand the program if they appear as part of the same expression.
The comma operator is often used in conjunction with the = operator, as follows:
$val = 26; $result = (++$val, $val + 5);
In this statement, the
++$val
operation is performed first, because it appears before the , operator. This adds 1 to $val, which means that $val now has the value 27. Then this new value of $val has 5 added to it, and the result, 32, is assigned to $result.
Note that the following expression is enclosed in parentheses:
++$val, $val + 5
This indicates that this set of operations is to be performed first. Had the parentheses not been present, the statement would have been
$result = ++$val, $val + 5;
In this case, everything before the comma would be performed first:
$result = ++$val
This means that $result would be assigned 27, not 32.
You'll learn more about parentheses and the order of operations later today, in the section titled "The Order of Operations."
The conditional operator also is borrowed from the C programming language. Unlike the other operators you've seen, the conditional operator requires three operands, as follows:
The first two operands are separated by the character ?, and the second and third operands are separated by the character :.
Here is a simple example of an expression that uses the conditional operator:
$result = $var == 0 ? 14 : 7;
Here, the test condition is the expression
$var == 0
If this expression is true, the value 14 is assigned to $result. If it is false, the value 7 is assigned to $result.
As you can see, the conditional operator behaves just like the if and else statements. The expression
$result = $var == 0 ? 14 : 7;
is identical to the following:
if ($var == 0) { $result = 14; } else { $result = 7; }
The difference between the conditional operator and the if-else construct is that the conditional operator can appear in the middle of expressions. For example, the conditional operator can be used as another way to prevent division by 0, as follows:
$result = 43 + ($divisor == 0 ? 0 : $dividend / $divisor);
Here, $result is assigned the value 43 plus the result of $dividend divided by $divisor, unless $divisor is 0. If $divisor is 0, the result of the division is assumed to be 0, and $result is assigned 43.
Listing 4.6 is a simple program that reads from the standard input file and compares the input line with a predetermined password.
Listing 4.6. A very simple password checker.
1: #!/usr/local/bin/perl 2: print ("Enter the secret password:\n"); 3: $password = "bluejays"; 4: $inputline = <STDIN>; 5: chop ($inputline); 6: $outputline = $inputline eq $password ? 7: "Yes, that is the correct password!\n" : 8: "No, that is not the correct password.\n"; 9: print ($outputline);
$ program4_6 Enter the secret password: orioles No, that is not the correct password. $
When you run program4_6 and type in a random password, you get the results shown in the Input-Output example.
The advantage of using the conditional operator here is that the assignment to $outputline occurs in only one place, and the statement is much more concise. If you use if and else, you need two assignments to $outputline and five lines, as follows:
if ($inputline eq $password) { $outputline = "Yes, that is the correct password!\n"; } else { $outputline = "No, that is not the correct password.\n"); }
Of course, the if and else statements are easier to use when things get more complex. Consider the following example:
if ($var1 == 47) { print("var1 is already 47\n"); $is_fortyseven = 1; } else { $var1 = 47; print("var1 set to 47\n"); $is_fortyseven = 0; }
You can write this using the conditional operator if you use the comma operator, as follows:
$var1 == 47 ? (print("var1 is already 47\n"), $is_fortyseven = 1) : ($var1 = 47, print("var1 set to 47\n"), $is_fortyseven = 0);
As you can see, this is difficult to understand. The basic rules are as follows:
In Perl 5, you can use the conditional operator on the left side of an assignment. This enables you to assign a value to either of two variables, depending on the result of a conditional expression.
$condvar == 43 ? $var1 : $var2 = 14;
This statement checks whether $condvar has the value 43. If it does, $var1 is assigned 14. If it doesn't, $var2 is assigned 14.
Normally, you won't want to use conditional operators in this way because your code will become difficult to follow. Although the following code is a little less efficient, it performs the same task in a way that is easier to understand:
$condvar == 43 ? $var1 = 14 : $var2 = 14;
Perl, like all programming languages, has a clearly defined set of rules that determine which operations are to be performed first in a particular expression. The following three concepts help explain these rules:
In grade school, you learned that certain arithmetic operations always are performed before other ones. For example, multiplication and division always are performed before addition and subtraction.
4 + 5 * 3
Here, the multiplication is performed first, even though the addition is encountered first when the statement is read from left to right. Because multiplication always is performed first, it has higher precedence than addition.
Table 4.6 defines the precedence of the operators in Perl. The
items at the top of the table have the highest precedence, and
the items at the bottom have the lowest.
Operator | Operation Performed |
++, -- | Autoincrement and autodecrement |
-, ~, ! | Operators with one operand |
** | Exponentiation |
=~, !~ | Pattern-matching operators |
*, /, %, x | Multiplication, division, remainder, repetition |
+, -, . | Addition, subtraction, concatenation |
<<, >> | Shifting operators |
-e, -r, etc. | File-status operators |
<, <=, >, >=, lt, le, gt, ge | Inequality-comparison operators |
==, !=, <=>, eq, ne, cmp | Equality-comparison operators |
& | Bitwise AND |
|, ^ | Bitwise OR and XOR |
&& | Logical AND |
|| | Logical OR |
.. | List-range operator |
? and : | Conditional operator (together) |
=, +=, -=, *=, | Assignment operators |
and so on | |
, | Comma operator |
not | Low-precedence logical NOT |
and | Low-precedence logical AND |
or, xor | Low-precedence logical OR and XOR |
Using this table, you can determine the order of operations in complicated expressions. For example:
$result = 11 * 2 + 6 ** 2 << 2;
To determine the order of operations in this expression, start at the top of Table 4.6 and work down. The first operator you see is **, which means that it is performed first, leaving
$result = 11 * 2 + 36 << 2;
The next operation you find in the table is the * operator. Performing the multiplication leaves the following:
$result = 22 + 36 << 2;
The + operator is next:
$result = 58 << 2;
Next up is the << operator:
$result = 232;
The = operator is last on the list and assigns 232 to $result.
You might have noticed that Table 4.6 contains some operators that you've not yet seen and which you'll learn about later:
The rules of operator precedence enable you to determine which operation to perform first when an expression contains different operators. But what should you do when an expression contains two or more operators that have the same precedence?
In some cases, it doesn't matter what order you perform the operations in. For example:
$result = 4 + 5 + 3;
Here, $result gets 12 no matter which addition is performed first. However, for some operations the order of evaluation matters.
$result = 2 ** 3 ** 2;
If you perform the leftmost exponentiation first, $result is assigned 8 ** 2, or 64. If you perform the rightmost exponentiation first, $result is assigned 2 ** 9, or 512.
Because the order of operations is sometimes important, Perl defines the order in which operations of the same precedence are to be performed. Operations that are performed right-to-left (with the rightmost operation performed first) are said to be right associative. Operations that are performed left-to-right (with the leftmost operation performed first) are left associative.
Table 4.7 lists the associativity for each of the Perl operators.
The operators are sorted according to precedence (in the same
order as Table 4.6).
Operator | Associativity |
++, -- | Not applicable |
-, ~, ! | Right-to-left |
** | Right-to-left |
=~, !~ | Left-to-right |
*, /, %, x | Left-to-right |
+, -, . | Left-to-right |
<<, >> | Left-to-right |
-e, -r, | Not applicable and so on |
<, <=, >, >=, lt, le, gt, ge | Left-to-right |
==, !=, <=>, eq, ne, cmp | Left-to-right |
& | Left-to-right |
|, ^ | Left-to-right |
&& | Left-to-right |
|| | Left-to-right |
.. | Left-to-right |
? and : | Right-to-left |
=, +=, -=, *=, | Right-to-left |
and so on | |
, | Left-to-right |
not | Left-to-right |
and | Left-to-right |
or, xor | Left-to-right |
From Table 4.7, you see that the exponentiation operator is right associative. This means that in the following:
$result = 2 ** 3 ** 2;
$result is assigned 512, because the rightmost ** operation is performed first.
Perl enables you to force the order of evaluation of operations in expressions. To do this, use parentheses as follows:
$result = 4 * (5 + 3);
In this statement, 5 is added to 3 and then multiplied by 4, yielding 32.
You can use as many sets of parentheses as you like:
$result = 4 ** (5 % (8 - 6));
Here, the result is 4:
DO use parentheses whenever you aren't sure whether a particular operation is to be evaluated first. For example, I don't know many programmers who remember that addition operators are evaluated before shifts: $result = 4 << 2 + 3; And virtually no one remembers that && has higher precedence than ||: if ($value == 0 || $value == 2 && $value2 == "hello") { You can make life a lot easier for people who read your code if you use parentheses when the order of evaluation is not obvious. For example: $result = 4 << (2 + 3); DO use multiple lines, extra spaces, and indentation to make complicated expressions easier to read. For example: if ($value == 0 || Here, it's obvious that there are two main conditions to be tested and that one of them contains a pair of subconditions. DON'T leave out closing parentheses by mistake. $result = 4 + (2 << ($value / 2); # error This statement will be flagged as erroneous because you are missing a closing parenthesis. A handy way of checking whether you have enough parentheses in complicated expressions is to use this simple trick:
If your final result is 0, you've got enough opening and closing parentheses. (This doesn't guarantee that you've put the parentheses in the right places, but at least you now know that you have enough of them.) |
Today you learned about the operators that Perl supports. Each operator requires one or more operands, which are the values on which the operator operates. A collection of operands and operators is known as an expression.
The operators you learned how to use are as follows:
You also learned about operator precedence and associativity, two concepts that tell you which operators in an expression usually are performed first. Operator precedence and associativity can be controlled by putting parentheses around the operations you want to perform first.
Q: | Is there a limit on how large my expressions can be? |
A: | Effectively, no. There is a limit, but it's so large that no one would possibly want to create an expression that long, because it would be impossible to read or understand.***It's easier to understand expressions if they are shorter. |
Q: | Is it better to use += or ++ when adding 1 to a variable? |
A: | It's best to use ++ when using a variable as a counter in a while statement (or in other loops, which you learn about on Day 8, "More Control Structures"). For other addition operations, you should use +=. |
Q: | Why are some operators left associative and others right associative? |
A: | Most operators are left associative, because we normally read from left to right.
Assignment is right associative because it's easier to read. For instance: $var1 = $var2 = 5; If assignment happened to be left associative, $var1 would be assigned the old value of $var2, not 5. This would not be obvious to a casual reader of the program.Exponentiation is right associative because that's how exponentiation is performed in mathematics.Other operators that are right associative are easier to read from right to left. |
The Workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to give you experience in using what you've learned. Try and understand the quiz and exercise answers before you go on to tomorrow's lesson.