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.
Table 4.1.
Integer-comparison operators.
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.
Table 4.2. String- and
numeric-comparison operators.
String Comparison Equivalent
operator operation 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:
$x == 0 || $y / $x > 5
$y / $x > 5
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
non-zero. 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.
***Begin do/don't***
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;
***Begin do/don't***
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.
***Begin do/don't***
DO remember that when you use the >> operator, the bits on the right are lost. For example:
$result1 = 17 >> 1; $result2 = 16 >> 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.
Table 4.3. The
assignment operators.
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 "exclusive
or" and assignment
Table 4.4 shows examples of the assignment operators, along
with equivalent statements that use operators you've seen earlier.
Table 4.4. Examples of
assignment operators.
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;
***Start TIP***
Tip: Don't use assignments in this way unless you absolutely have to. At first glance, the statement
($a = $b) += 3;
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 everything 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).
Table 4.5. Condition
evaluation.
$value at $value
time of test Result after test 0 true (0 <= 5) 1 1 true
(1 <= 5) 2 2 true (2 <= 5) 3 3 true (3 <= 5) 4 4 true (4
<= 5) 5 5 true (5 <= 5) 6 6 false (6 <= 5) 7 (exit while)
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.
***Begin do/don't***
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; $var2 = $var1 + ++$var1;
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"
***Begin CAUTION***
Caution: Incrementing string values using ++ works only if the variable has not already been converted to a number.
$stringvar = "abc"; $stringvar += 5; $stringvar++;
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"; $stringvar++; $stringvar = "ab5c"; $stringvar++;
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.
***Begin do/don't***
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 $newstring = $oldstringx 5; # incorrect $newstring = $oldstring x5; # also incorrect
Normally, you don't need to put spaces between an operator and its operands.
$x = $x + 1; # this is OK $x=$x+1; # this is also 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.
Table 4.6. Operator
precedence.
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 "exclusive or" &&
Logical "and" || Logical "or" ..
List-range operator ? and : Conditional operator
(together) =, +=, -=, *=, and so on
Assignment operators , 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).
Table 4.7. Operator
associativity.
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, and so on Not applicable <, <=, >, >=, 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 =, +=, =, *=, and
so on Right-to-left , 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
$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:
***Begin do/don't***
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") {
print("my condition is true\n");
}
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);
if ($value == 0 || ($value == 2 && $value2 == "hello")) {
print("my condition is true\n");
}
DO use multiple lines, extra spaces, and indentation to make complicated expressions easier to read. For example:
if ($value == 0 ||
($value == 2 && $value2 == "hello")) {
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:
***begin BL list within a sidebar
**end BL list
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.
$var1 = $var2 = 5;
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.
if ($var1 == 5 || $var2 == 7) {
$result = $var1 * $var2 + 16.5;
} else {
print("condition is false\n");
$result = 0;
}
$result = $var1 <= 26 ? ++$var2 : 0;
$result = 5.1 + 100005.2 100005.2;
$result = $var1 * 2 << 5 + 3 || $var2 ** 3, $var3;
$var1 = 43; $var2 = 16; $result = ++$var2 == 17 ? $var1++ * 2 - 5 : ++$var1 * 3 11;