Chapter 4

Operators


CONTENTS

The operators in a computer language tell the computer what actions to perform. Perl has more operators than most languages. You've already seen some operators-like the equals or assignment operator(=)-in this book. As you read about the other operators, you'll undoubtedly realize that you are familiar with some of them. Trust your intuition; the definitions that you already know will probably still be true.

Operators are instructions you give to the computer so that it can perform some task or operation. All operators cause actions to be performed on operands. An operand can be anything that you perform an operation on. In practical terms, any particular operand will be a literal, a variable, or an expression. You've already been introduced to literals and variables. A good working definition of expression is some combination of operators and operands that are evaluated as a unit. Chapter 6 "Statements," has more information about expressions.

Operands are also recursive in nature. In Perl, the expression 3 + 5-two operands and a plus operator-can be considered as one operand with a value of 8. For instaNCe, (3 + 5) - 12 is an expression that consists of two operands, the second of which is subtracted from the first. The first operand is (3 + 5) and the second operand is 12.

This chapter will discuss most of the operators available to you in Perl . You'll find out about many operator types and how to determine their order of precedeNCe. And, of course, you'll see many examples.

PrecedeNCe is very important in every computer language and Perl is no exception. The order of precedeNCe indicates which operator should be evaluated first.

I like to think about operators in the same way I would give instructions to the driver of a car. I might say "turn left" or "turn right." These commands could be considered directional operators in the same way that + and - say "add this" or "subtract this." If I yell "stop" while the car is moving, on the other hand, it should supersede the other commands. This means that "stop" has precedeNCe over "turn left" and "turn right." The "Order of PrecedeNCe" section later in this chapter will discuss precedeNCe in more detail.

Operator Types

Perl supports many types of operators. Table 4.1 shows all of the operator types in the Perl language. This chapter discusses the more commonly used types in detail. You can learn about any type not discussed in this chapter by looking in the chapter refereNCed in that type's description in Table 4.1.

Table 4.1  The Perl Operator Types

Operator TypesDescription
ArithmeticThese operators mirror those you learned in grade school. Addition, Subtraction, and Multiplication are the bread and butter of most mathematical statements.
AssignmentThese operators are used to assign a value to a variable. Algebra uses assignment operators. For example, in the statement X = 6, the equal sign is the assignment operator.
BindingThese operators are used during string comparisons and are ex-plained in Chapter 10, "Regular Expressions."
BitwiseThese operators affect the individual bits that make up a value. For example, the value 3 is also 11 in binary notation or ((1 ¥ 2) + 1). Each character in binary notation represents a bit, which is the smallest piece of a computer's memory that you can modify.
CommaThe comma operator has two fuNCtions. It serves to separate array or list elements (see Chapter 2 "Numeric and String Literals") and it serves to separate expressions (see Chapter 6 "Statements").
File TestThese operators are used to test for various conditions associated with files. You can test for file existeNCe, file type, and file access rights among other things. See Chapter 9 "Using Files," for more information.
ListList operators are funny things in Perl. They resemble fuNCtion calls in other languages. List operators are discussed in Chapter 5 "FuNCtions."
LogicalThese operators implement Boolean or true/false logic. In the senteNCe "If John has a fever AND John has clogged sinuses OR an earache AND John is NOT over 60 years old, then John has a cold," the AND, OR, and NOT are acting as logical operators. The low precedeNCe logical operators will be discussed separately in Chapter 13, "Handling Errors and Signals."
Numeric RelationalThese operators allow you to test the Relationalrelationship of one numeric variable to another. For example, is 5 GREATER THAN 12?
PostfixA member of this group of opera-tors-(), [], {}- appears at the end of the affected objects. You've already seen them used in Chapter 3 "Vari-ables" for arrays and associative arrays. The parentheses operators are also used for list operators as discussed in Chapter 5 "FuNCtions."
RangeThe range operator is used to create a range of elements in arrays. It can also be used in a scalar context.
RefereNCeThe refereNCe operators are used to manipulate variables. For more information, see Chapter 8 "Refer-eNCes."
StringThe string coNCatenation operator is used to join two strings together. The string repetition operator is used to repeat a string.
String RelationalThese operators allow you to test the relationship of one string variable to another. For example, is "abc" GREATER THAN "ABC"?
TernaryThe ternary operator is used to choose between two choices based on a given condition. For instaNCe: If the park is within one mile, John can walk; otherwise, he must drive.

The Binary Arithmetic Operators

There are six binary arithmetic operators: addition, subtraction, multiplication, exponentiation, division, and modulus. While you may be unfamiliar with the modulus operator, the rest act exactly as you would expect them to. Table 4.2 lists the arithmetic operators that act on two operands-the binary arithmetic operators. In other words, the addition (+) operator can be used to add two numbers together like this: 4 + 5. The other binary operators act in a similar fashion.

Table 4.2  The Binary Arithmetic Operators

Operator
Description
op1 + op2
Addition
op1 - op2
Subtraction
op1 * op2
Multiplication
op1 ** op2
Exponentiation
op1 / op2
Division
op1 % op2
Modulus

Example: The Exponentiation Operator

The exponentiation operator is used to raise a number to a power. For instaNCe, 2 **4 is equivalent to 2 * 2 * 2 * 2, which equals 16. You'll occasionally see a refereNCe to when exponentiation discussion turns to how efficient a given algorithm is, but I've never needed it for my everyday programming tasks. In any case, here's a quick look at how it works.

This example shows how to raise the number 4 to the 3rd power, which is equivalent to 4 * 4 * 4 or 64.

Assign $firstVar the value of 4.
Raise 4 to the 3rd power using the exponentiation operator and assign the new value to
$secondVar.
Print
$secondVar.

$firstVar = 4;

$secondVar = $firstVar ** 3;

print("$secondVar\n");

This program produces the following output:


64

Example: The Modulus Operator

The modulus operator is used to find the remainder of the division between two integer operands. For instaNCe, 10 % 7 equals 3 because 10 / 7 equals 1 with 3 left over.

I've found the modulus operator to be useful when my programs need to run down a list and do something every few items. This example shows you how to do something every 10 items.

Start a loop that begins with $index equal to zero.
If the value of
$index % 10 is equal to zero then the print statement will be executed.
Print the value of
$index followed by space.
The program will iNCrease the value of
$index by one and then loop back to the start of the if statement.

Listing 4.1  O4LST01.PL-How to Display a Message Every Ten Items

for ($index = 0; $index <= 100; $index++) {

    if ($index % 10 == 0) {

        print("$index ");

    }

}


When this program is run, the output should look like the following:


0 10 20 30 40 50 60 70 80 90 100

Notice that every tenth item is printed. By changing the value on the right side of the modulus operator, you can affect how many items are processed before the message is printed. Changing the value to 15 means that a message will be printed every 15 items. Chapter 7 "Control Statements," describes the if and for statement in detail.

The Unary Arithmetic Operators

The unary arithmetic operators act on a single operand. They are used to change the sign of a value, to iNCrement a value, or to decrement a value. INCrementing a value means to add one to its value. Decrementing a value means to subtract one from its value. Table 4.3 lists Perl's unary operators.

Table 4.3  The Unary Arithmetic Operators

Operator
Description
Changing the sign of op1
+op1
Positive operand
-op1
Negative operand
Changing the value of op1 before usage
++op1
Pre-iNCrement operand by one
--op1
Pre-decrement operand by one
Changing the value of op1 after usage
op1++
Post-iNCrement operand by one
op1--
Post-decrement operand by one

Arithmetic operators start to get complicated when unary operators are introduced. Just between you and me, I didn't get the hang of negative numbers until someone said: "If you have five pieces of chocolate, and add negative two pieces…"

You might think that adding negative numbers is strange. Not so. I know that you will never write a mathematics statement such as the following: 345 + -23. However, you might use 354 + $gasBill, where $gasBill represents a 23-dollar debit-in other words, a negative number.

Using the unary plus operator does nothing, and Perl ignores it. The unary negative operator, however, changes the meaning of a value from positive to negative or vice versa. For instaNCe, if you had a variable called $firstVar equal to 34, then printing -$firstVar would display -34.

The ++ and -- operators are examples of the Perl shorthand notation. If the ++ or -- operators appear in front of the operand, the operand is iNCremented or decremented before its value is used. If the ++ or -- operators appear after the operand, then the value of the operand is used and then the operand is iNCremented or decremented as required.

Example: The Pre-iNCrement Operator

This example shows how to use the pre-iNCrement operator (++).

The $numPages variable is assigned a value of 5.
The
$numPages variable is iNCremented by 1.
The
$numPages variable is printed.
The
$numPages variable is assigned a value of 5.
The
$numPages variables are iNCremented using the pre-iNCrement operator and then printed.

Listing 4.2  04LST02.PL-Using Pre-iNCrement Operator

# Original Way

$numPages = 5;

$numPages = $numPages + 1;

print($numPages, "\n");



# New Way

$numPages = 5;

print(++$numPages, "\n");


This program produces the following output:


6

6

You can see that the new way of coding is shorter than the original way. The statement print(++$numPages, "\n"); will first iNCrement the $numPages variable and then allow the print command to use it.

Example: The Pre-decrement Operator

This example shows how to use the pre-decrement operator (--).

The $numPages variable is assigned a value of 5.
The
$numPages variable is decremented by 1.
The
$totalPages variable is assigned the value of $numPages + 5.
The
$numPages and $totalPages variables are printed.
The
$numPages variable is assigned a value of 5.
The
$numPages variable is decremented and then $numPages + 5 is assigned to $totalPages.
The
$numPages and $totalPages variables are printed.

Listing 4.3  04LST03.PL-Using Pre-iNCrement Operator

# Original Way

$numPages = 5;

$numPages = $numPages - 1;

$totalPages = $numPages + 5;

print("$numPages $totalPages \n");



# New Way

$numPages = 5;

$totalPages = --$numPages + 5;

print("$numPages $totalPages \n");


This program produces the following output:


4 9

4 9

The statement $totalPages = --$numPages + 5; will first decrement the $numPages variable and then allow the plus operator to use it.

Example: The Post-iNCrement Operator

This example shows how to use the ++ and -- post-iNCrement operators.

The $numPages variable is assigned a value of 5.
The
$totalPages variable is assigned the value of $numPages.
The
$numPages variable is iNCremented by one.
The
$numPages and $totalPages variables are printed.
The
$numPages variable is assigned a value of 5.
The
$totalPages variable is assigned the value of $numPages and then the $numPages variable is iNCremented.
The
$numPages and $totalPages variables are printed.

Listing 4.4  04LST04.PL-Using Pre-iNCrement Operator

# Original Way

$numPages = 5;

$totalPages = $numPages;

$numPages = $numPages + 1;

print("$numPages $totalPages \n");



# New Way

$numPages = 5;

$totalPages = $numPages++;

print("$numPages $totalPages \n");


The program produces the following output:


6 5

6 5

The statement $totalPages = $numPages++; will first assign the value of $numPages to $totalPages and then iNCrement the $numPages variable. It may help to know that post-iNCrement and post-decrement operators do not affect the value of the variable on the left side of the assignment operator. If you see post-iNCrement or post-decrement operators, evaluate the statement by ignoring them. Then, when done, apply the post-iNCrement and post-decrement operators as needed.

Tip
The Perl programming language has many ways of achieving the same objective. You will become a more efficient programmer if you decide on one approach to iNCrementing/decrementing and use it consistently.

The Logical Operators

Logical operators are mainly used to control program flow. Usually, you will find them as part of an if, a while, or some other control statement. Control statements are discussed in Chapter 7 "Control Statements."

Table 4.4  The Logical Operators

Operator
Description
op1 && op2
Performs a logical AND of the two operands.
op1 || op2
Performs a logical OR of the two operands.
!op1
Performs a logical NOT of the operand.

The coNCept of logical operators is simple. They allow a program to make a decision based on multiple conditions. Each operand is considered a condition that can be evaluated to a true or false value. Then the value of the conditions is used to determine the overall value of the op1 operator op2 or !op1 grouping. The following examples demonstrate different ways that logical conditions can be used.

Example: The "AND" Operator (&&)

The && operator is used to determine whether both operands or conditions are true. Table 4.5 shows the results of using the && operator on the four sets of true/false values.

Table 4.5  The && Result Table

Op1
Op2
Op1 && Op2
0
0
0
1
0
0
0
1
0
1
1
1

If the value of $firstVar is 10 AND the value of $secondVar is 9, then print the error message.

if ($firstVar == 10 && $secondVar == 9) {

    print("Error!");

};

If either of the two conditions is false or iNCorrect, then the print command is bypassed.

Example: The "OR" Operator (||)

The || operator is used to determine whether either of the conditions is true. Table 4.6 shows the results of using the || operator on the four sets of true/false values.

Table 4.6  The || Result Table

0p1
0p2
0p1 || 0p2
0
0
0
1
0
1
0
1
1
1
1
1

If the value of $firstVar is 9 OR the value of $firstVar is 10, then print the error message.

if ($firstVar == 9 || $firstVar == 10) {

    print("Error!");

If either of the two conditions is true, then the print command is run.

Caution
If the first operand of the || operator evaluates to true, the second operand will not be evaluated. This could be a source of bugs if you are not careful. For instaNCe, in the following code fragment:
if ($firstVar++ || $secondVar++) { print("\n"); }
variable $secondVar will not be iNCremented if $firstVar++ evaluates to true.

Note
You might be tempted to try the following:
if ($firstVar == (9 || 10)) {
    print("Error!");
};
to determine if $firstVar is equal to either 9 or 10. Don't do it. Perl doesn't work this way. First, the expression (9 || 10) will be evaluated to be equal to 9. And then, Perl will evaluate $firstVar == 9. The correct method for testing $firstVar is to explicitly state each sub-condition that needs to be met in order for the entire condition to return true. The correct way is:
if ($firstVar == 9 || $firstVar == 10) {
    print("Error!");
};

Example: The "NOT" Operator (!)

The ! operator is used to convert true values to false and false values to true. In other words, it inverts a value. Perl considers any non-zero value to be true-even string values. Table 4.7 shows the results of using the ! operator on true and false values.

Table 4.7  The ! Result Table

Op1
!Op1
0
1
1
0

Assign a value of 10 to $firstVar.
Negate
$firstVar-!10 is equal to 0-and assign the new value to $secondVar.
If the
$secondVar variable is equal to zero, then print the string "zero."

$firstVar = 10;

$secondVar = !$firstVar;



if ($secondVar == 0) {

   print("zero\n");

};

The program produces the following output:


zero

You could replace the 10 in the first line with "ten," 'ten,' or any non-zero, non-null value.

The Bitwise Operators

The bitwise operators, listed in Table 4.8, are similar to the logical operators, except that they work on a smaller scale.

Table 4.8  The Bitwise Operators

Operator
Description
op1 & op2
The AND operator compares two bits and generates a result of 1 if both bits are 1; otherwise, it returns 0.
op1 | op2
The OR operator compares two bits and generates a result of 1 if the bits are complementary; otherwise, it returns 0.
op1 ^ op2
The EXCLUSIVE-OR operator compares two bits and gener-ates a result of 1 if either or both bits are 1; otherwise, it returns 0.
~op1
The COMPLEMENT operator is used to invert all of the bits of the operand. I've never found this useful, so we'll skip looking at an example of it.
op1 >> op2
The SHIFT RIGHT operator moves the bits to the right, discards the far right bit, and assigns the leftmost bit a value of 0. Each move to the right effectively divides op1 in half.
op1 << op2
The SHIFT LEFT operator moves the bits to the left, discards the far left bit, and assigns the rightmost bit a value of 0. Each move to the left effectively multiplies op1 by 2.

Note
Both operands associated with the bitwise operator must be integers.

Bitwise operators are used to change individual bits in an operand. A single byte of computer memory-when viewed as 8 bits-can signify the true/false status of 8 flags because each bit can be used as a boolean variable that can hold one of two values: true or false. A flag variable is typically used to indicate the status of something. For instaNCe, computer files can be marked as read-only. So you might have a $fReadOnly variable whose job would be to hold the read-only status of a file. This variable is called a flag variable because when $fReadOnly has a true value, it's equivalent to a football referee throwing a flag. The variable says, "Whoa! Don't modify this file."

When you have more than one flag variable, it might be more efficient to use a single variable to indicate the value of more than one flag. The next example shows you how to do this.

Example: Using the &, |, and ^ Operators

The first step to using bitwise operators to indicate more than one flag in a single variable is to define the meaning of the bits that you'd like to use. Figure 4.1 shows an example of 8 bits that could be used to control the attributes of text on a display.

Figure 4.1 : The bit definition of a text attribute control variable.

If you assume that $textAttr is used to control the text attributes, then you could set the italic attribute by setting $textAttr equal to 128 like this:


$textAttr = 128;

because the bit pattern of 128 is 10000000. The bit that is turned on corresponds to the italic position in $textAttr.

Now let's set both the italic and underline attributes on at the same time. The underline value is 16, which has a bit pattern of 00010000. You already know the value for italic is 128. So we call on the OR operator to combine the two values.


$textAttr = 128 | 16;

or using the bit patterns (this is just an example-you can't do this in Perl)


$textAttr = 10000000 | 00010000;

If you look back at Table 4.8 and evaluate each bit, you will see that $textAttr gets assigned a value of 144 (or 10010000 as a bit pattern). This will set both italic and underline attributes on.

The next step might be to turn the italic attribute off. This is done with the EXCLUSIVE-OR operator, like so:


$textAttr = $textAttr ^ 128;

Example: Using the >> and << Operators

The bitwise shift operators are used to move all of the bits in the operand left or right a given number of times. They come in quite handy when you need to divide or multiply integer values.

This example will divide by 4 using the >> operator.

Assign a value of 128 to the $firstVar variable.
Shift the bits inside
$firstVar two places to the right and assign the new value to $secondVar.
Print the
$secondVar variable.

$firstVar = 128;

$secondVar = $firstVar >> 2;

print("$secondVar\n");

The program produces the following output:


32

Let's look at the bit patterns of the variables before and after the shift operation. First, $firstVar is assigned 128 or 10000000. Then, the value in $firstVar is shifted left by two places. So the new value is 00100000 or 32, which is assigned to $secondVar.

The rightmost bit of a value is lost when the bits are shifted right. You can see this in the next example.

This example will divide by 8 using the >> operator.

Assign a value of 129-a bit pattern of 10000001-to $firstVar. Every odd value has the rightmost bit set.
Shift the bits inside
$firstVar three places to the right and assign the new value to $secondVar.
Print the
$secondVar variable.

$firstVar = 129;

$secondVar = $firstVar >> 3;

print("$secondVar\n");

The program produces the following output:


16

SiNCe the bit value of 16 is 00010000, you can tell that the rightmost bit has disappeared.

Here's a quick example using the << operator. We'll multiply 128 by 8.

Assign a value of 128 to the $firstVar variable.
Shift the bits inside
$firstVar two places to the left and assign the new value to $secondVar.
Print the
$secondVar variable.

$firstVar = 128;

$secondVar = $firstVar << 3;

print $secondVar;

The program produces the following output:


1024

The value of 1024 is beyond the bounds of the 8 bits that the other examples used. This was done to show you that the number of bits available for your use is not limited to one byte. You are really limited by however many bytes Perl uses for one scalar variable-probably 4. You'll need to read the Perl documentation that came with the interpreter to determine how many bytes your scalar variables use.

The Numeric Relational Operators

The numeric relational operators, listed in Table 4.9, are used to test the relationship between two operands. You can see if one operand is equal to another, if one operand is greater than another, or if one operator is less than another.

Note
It is important to realize that the equality operator is a pair of equal signs and not just one. Quite a few bugs are introduced into programs because people forget this rule and use a single equal sign when testing conditions.

Table 4.9  The Numeric Relational Operators

Operator
Description
The Equality Operators
op1 == op2
This operator returns true if op1 is equal to op2. For example, 6 == 6 is true.
op1 != op2
This operator returns true if op1 is not equal to op2. For example, 6 != 7 is true.
The Comparison Operators
op1 < op2
This operator returns true if op1 is less than op2. For example, 6 < 7 is true.
Op1 <= op2
This operator returns true if op1 is less than or equal to op2. For example, 7 <= 7 is true.
op1 > op2
This operator returns true if op1 is greater than op2. For example, 6 > 5 is true.
op1 >= op2
This operator returns true if op1 is greater than or equal to op2. For example, 7 >= 7 is true.
op1 <=> op2
This operator returns 1 if op1 is greater than op2, 0 if op1 equals op2, and -1 if op1 is less than op2.

You will see many examples of these operators when you read about controlling program flow in Chapter 7 "Control Statements." Therefore, I'll show only an example of the <=> comparison operator here.

Example: Using the <=> Operator

The number comparison operator is used to quickly tell the relationship between one operand and another. It is frequently used during sorting activities.

Tip
You may sometimes see the <=> operator called the spaceship operator because of the way that it looks.

Set up three variables.
Print the relationship of each variable to the variable
$midVar.

$lowVar =  8;

$midVar = 10;

$hiVar  = 12;



print($lowVar <=> $midVar, "\n");

print($midVar <=> $midVar, "\n");

print($hiVar  <=> $midVar, "\n");

The program produces the following output:


-1

0

1

The -1 indicates that $lowVar (8) is less than $midVar (10). The 0 indicates that $midVar is equal to itself. And the 1 indicates that $hiVar (12) is greater than $midVar (10).

The String Relational Operators

The string relational operators, listed in Table 4.10, are used to test the relationship between two operands. You can see if one operand is equal to another, if one operand is greater than another, or if one operator is less than another.

Table 4.10  The String Relational Operators

Operator
Description
The Equality Operators
op1 eq op2
This operator returns true if op1 is equal to op2. For example, "b" eq "b" is true.
Op1 ne op2
This operator returns true if op1 is not equal to op2. For example, "b" ne "c" is true.
The Comparison Operators
op1 lt op2
This operator returns true if op1 is less than op2. For example, "b" lt "c" is true.
Op1 le op2
This operator returns true if op1 is less than or equal to op2. For example, "b" le "b" is true.
Op1 gt op2
This operator returns true if op1 is greater than op2. For example, "b" gt "a" is true.
Op1 ge op2
This operator returns true if op1 is greater than or equal to op2. For example, "b" ge "b" is true.
Op1 cmp op2
This operator returns 1 if op1 is greater than op2, 0 if op1 equals op2, and -1 if op1 is less than op2.

String values are compared using the ASCII values of each character in the strings. You will see examples of these operators when you read about control program flow in Chapter 7 "Control Statements." So, we'll only show an example of the cmp comparison operator here. You may want to glaNCe at Appendix E, "ASCII Table," to see all of the possible ASCII values.

Example: Using the cmp Operator

The string comparison operator acts exactly like the <=> operator except that it is designed to work with string operands. This example will compare the values of three different strings.

Set up three variables.
Print the relationship of each variable to the variable
$midVar.

$lowVar = "AAA";

$midVar = "BBB";

$hiVar  = "ccC";



print($lowVar cmp $midVar, "\n");

print($midVar cmp $midVar, "\n");

print($hiVar  cmp $midVar, "\n");

The program produces the following output:


-1

0

1

Notice that even though strings are being compared, a numeric value is returned. You may be wondering what happens if the strings have spaces in them. Let's explore that for a moment.


$firstVar = "AA";

$secondVar = " A";

print($firstVar cmp $secondVar, "\n");

The program produces the following output:


1

which means that "AA" is greater than " A" according to the criteria used by the cmp operator.

The Ternary Operator

The ternary is actually a sequeNCe of operators. The operator is used like this:


CONDITION-PART ? TRUE-PART : FALSE-PART

which is shorthand for the following statement:


if (CONDITION-PART) {

    TRUE-PART

} else {

    FALSE-PART

}

You can find more information about if statements in Chapter 7 "Control Statements."

The value of the entire operation depends on the evaluation of the CONDITION-PART section of the statement. If the CONDITION-PART evaluates to true, then the TRUE-PART is the value of the entire operation. If the CONDITION-PART evaluates to false, then the FALSE-PART is the value of the entire operation.

Tip
The ternary operator is also referred to as the conditional operator by some refereNCes.

Example: Using the Ternary Operator to Assign Values

I frequently use the ternary operator to assign a value to a variable when it can take one of two values. This use of the operator is fairly straightforward.

If $firstVar is zero, then assign $secondVar a value of zero. Otherwise, assign $secondVar the value in the first element in the array @array.

$secondVar = ($firstVar == 0) ? 0 : $array[0];

The ternary operator can also be used to control which code sections are performed. However, I recommend against this use because it makes the program harder to read. I believe that operators should affect variables, not program flow.

The CONDITION-PART evaluates to true so the $firstVar variable is iNCremented.

1 ? $firstVar++ : $secondVar++;

The CONDITION-PART evaluates to false so the $secondVar variable is iNCremented.

0 ? $firstVar++ : $secondVar++;

In this example, you get a chaNCe to see how the language can be abused. When you have more than two actions to consider, you can nest ternary operators inside each other. However, as you can see the result is confusing code.

Assign one of four values to $firstVar depending on the value of $temp.

$firstVar = $temp == 0 ? 

                $numFiles++ : 

                ($temp == 1 ? 

                    $numRecords++ : 

                    ($temp == 3 ? $numBytes++ : $numErrors++));


Tip
Abusing the language in this manner will make your programs difficult to understand and maintain. You can use the if statement for better looking and more maintainable code. See Chapter 7 "Control Statements," for more information.

If you'd like to see a really strange use of the ternary operator, take a look at this next example. It uses the ternary operator to determine which variable gets assigned a value.


$firstVar = 1;

$secondVar = 1;



$thirdVar = 1;



($thirdVar == 0 ? $firstVar : $secondVar) = 10;



print "$firstVar\n";

print "$secondVar\n";

print "$thirdVar\n";

The program produces the following output:


1

10

1

The line ($thirdVar == 0 ? $firstVar : $secondVar) = 10; is equivalent to the following control statement:


if ($thirdVar ==0) {

    $firstVar = 10;

} else {

    $secondVar = 10;

}

This use of the ternary operator works because Perl lets you use the results of evaluations as lvalues. An lvalue is anything that you can assign a value to. It's called an lvalue because it goes on the left side of an assignment operator.

Note
Some programmers might think that this use of the ternary operator is as bad as using it to control program flow. However, I like this ability because it gives you the ability to coNCisely determine which variable is the target of an assignment.

The Range Operator (..)

The range operator was already introduced to you in Chapter 3 "Variables," when you read about arrays. I review its use here-in an array context-in a bit more detail.

Example: Using the Range Operator

When used with arrays, the range operator simplifies the process of creating arrays with contiguous sequeNCes of numbers and letters. We'll start with an array of the numbers one through ten.

Create an array with ten elements that iNClude 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10.

@array = (1..10);

You can also create an array of contiguous letters.

Create an array with ten elements that iNClude A, B, C, D, E, F, G, H, I , and J.

@array = ("A".."J");

And, of course, you can have other things in the array definition besides the range operator.

Create an array that iNCludes AAA, 1, 2, 3, 4, 5, A, B, C, D, and ZZZ.

@array = ("AAA", 1..5, "A".."D", "ZZZ");

You can use the range operator to create a list with zero-filled numbers.

Create an array with ten elements that iNClude the strings 01, 02, 03, 04, 05, 06, 07, 08, 09, and 10.

@array = ("01".."10");

And you can use variables as operands for the range operator.

Assign a string literal to $firstVar.
Create an array with ten elements that iNClude the strings 01, 02, 03, 04, 05, 06, 07, 08, 09, and 10.

$firstVar = "10";

@array = ("01"..$firstVar);

If you use strings of more than one character as operands, the range operator will iNCrement the rightmost character by one and perform the appropriate carry operation when the number 9 or letter z is reached. You'll probably need to see some examples before this makes sense. I know that I had trouble figuring it out. So here goes.

You've already seen "A".."Z," which is pretty simple to understand. Perl counts down the alphabet until Z is reached.

Caution
The two ranges "A".."Z" and "a".."Z" are not identical. And the second range does not contain all lowercase letters and all uppercase letters. Instead, Perl creates an array that contains just the lowercase letters. Apparently, when Perl reaches the end of the alphabet-whether lowercase or uppercase-the iNCrementing stops.

What happens when a two-character string is used as an operand for the range operator? Let's find out.

Create an array that iNCludes the strings aa, ab, ac, ad, ae, and af.

@array = ("aa" .. "af");

This behaves as you'd expect, iNCrementing along the alphabet until the f letter is reached. However, if you change the first character of one of the operands, watch what happens.

Create an array that iNCludes the strings ay, az, ba, bb, bc, bd, be, and bf.

@array = ("ay" .. "bf");

When the second character is iNCremented to z, then the first character is iNCremented to b and the second character is set to a.

Note
If the right side of the range operator is greater than the left side, an empty array is created.

The String Operators (. and x)

Perl has two different string operators-the coNCatenation (.) operator and the repetition (x) operator. These operators make it easy to manipulate strings in certain ways. Let's start with the coNCatenation operator.

Example: Using the CoNCatenation Operator

The coNCatenation operator is used to join two strings together. If you have a numeric value as one of the two operands, Perl will quietly convert it to a string.

Here is an example that shows Perl converting a number into a string.

Assign a string value to $firstVar. The string will be three values coNCatenated into one string.

$firstVar = "This box can hold " . 55 . " items.";

print("$firstVar\n");

The program produces the following output:


This box can hold 55 items.

The number 55 is automatically converted to a string and then combined with the other strings. Notice that the string literals have spaces in them so that when the final string is created, the number will be surrounded with spaces, making the senteNCe readable.

You can also use variables as operands with the coNCatenation operator.

Assign string values to $firstVar and $secondVar.
Assign the coNCatenation of
$firstVar and $secondVar to $thirdVar.
Print
$thirdVar.

$firstVar = "AAA";

$secondVar = "BBB";

$thirdVar = $firstVar . $secondVar;

print("$thirdVar\n");

The program produces the following output


AAABBB

Notice that Perl coNCatenates the strings together without adding any spaces or other separating characters. If you want a space between the string after they are coNCatenated, you must ensure that one of original strings has the space character-either at the end of the first string or the start of the second.

Example: Using the Repetition Operator

The repetition operator is used to repeat any string a given number of times. Like the coNCatenation operator, any numbers will be quietly converted to strings so that they can be repeated.

Here is an example that shows how to repeat a string 7 times.

Assign $firstVar the value of "1".
Assign
$secondVar the value of $firstVar repeated seven times.
Print
$secondVar.

$firstVar = "1";

$secondVar = $firstVar x 7;

print("$secondVar\n");

The program produces the following output:


1111111

The string that gets repeated can be longer than one character.

Assign $firstVar the value of "11 ".
Assign
$secondVar the value of $firstVar repeated seven times.
Print
$secondVar.

$firstVar = "11 ";

$secondVar = $firstVar x 7;

print("$secondVar\n");

The program produces the following output:


11 11 11 11 11 11 11

You can also use the repetition operator on arrays or lists. However, the array gets evaluated in a scalar context so that the number of elements is returned. This number gets converted to a string and then repeated.

Assign the elements "A" through "G" to @array.
Get the number of elements in
@array, convert that number to a string, repeat it twice, and then assign the new string to $firstVar.
Print the
@array and $firstVar variables.

@array = ('A'..'G');

$firstVar = @array x 2;

print("@array\n");

print("$firstVar\n");

This program produces the following output:


A B C D E F G

77

Tip
If you want to repeat an array element, explicitly say which element you want to repeat, using an array index.

The Assignment Operators

The last type of operators that we'll look at are assignment operators. You've already used the basic assignment operator (=) to value variables in some of the examples earlier in this chapter. In addition, Perl has shortcut assignment operators that combine the basic assignment operator with another operator. For instaNCe, instead of saying $firstVar = $firstVar + $secondVar you could say $firstVar += $secondVar. The advantage of the using shortcut operators-besides having less to type-is that your intentions regarding assignment are made clear.

Table 4.11 lists all of Perl's assignment operators. After reading the other sections in this chapter about the various operator types, you should be familiar with all of the operations described in the table.

Table 4.11  The Assignment Operators

Operator
Description
var = op1;
This operator assigns the value of op1 to var.
var += op1;
This operator assigns the value of var + op1 to var.
var -= op1;
This operator assigns the value of var - op1 to var.
var *= op1;
This operator assigns the value of var * op1 to var.
var /= op1;
This operator assigns the value of var / op1 to var.
var %= op1;
This operator assigns the value of var % op1 to var.
var .= op1;
This operator assigns the value of var . op1 to var.
var **= op1;
This operator assigns the value of var ** op1 to var.
var x= op1;
This operator assigns the value of var x op1 to var.
var <<= op1;
This operator assigns the value of var << op1 to var.
var >>= op1;
This operator assigns the value of var >> op1 to var.
var &= op1;
This operator assigns the value of var & op1 to var.
var |= op1;
This operator assigns the value of var | op1 to var.
var ||= op1;
This operator assigns the value of var || op1 to var.
var ^= op1;
This operator assigns the value of var ^ op1 to var.

The examples in this section will not describe the different assignment operators. Their use is straightforward. However, when assigning values to arrays, there are some special situations. The first is assigning values to array slices and the second is assigning array elements to scalars. Let's start with array slices.

Example: Assignment Using Array Slices

If you recall from Chapter 3 "Variables," array slices let you directly access multiple elements of an array using either the comma or range operators. For instaNCe, the variable @array(10, 12) refers to both the tenth and the twelfth elements of the @array array.

You can use the assignment operator in conjuNCtion with array slices to assign values to multiple array elements in one statement. If you have an array with 10 elements and you need to change elements 4 and 7, you can do so like this:

Create an array with 10 elements.
Assign values to elements 4 and 7.
Print the array.

@array = (0..10);

@array[4, 7] = ("AA","BB");

print("@array\n");

This program produces the following output:


0 1 2 3 AA 5 6 BB 8 9 10

Tip
The elements to which an array slice refers do not have to be in consecutive order.

You can look at the array slice assignment in the following way. The array on the left is the target and the array on the right is the source. So, the target array gets assigned the values in the source array.

There are a number of variations on the basic idea of using array slices in assignment statements. You can use scalar variables in place of the literals as operands for the range operator.

Create an array with 10 elements.
Assign values to elements 4 and 7.
Print the array.

$firstVar = "AA";

@array = (0..10);

@array[4, 7] = ($firstVar, $firstVar);

print("@array\n");

This program produces the following output:


0 1 2 3 AA 5 6 AA 8 9 10

And you can use array variables, also.

Create an array with 10 elements and an array with 2 elements.
Assign values to elements 4 and 7 of the
@array1 array.
Print
@array1.

@array1 = (0..10);

@array2 = ("AA", "BB");

@array1[4, 7] = @array2;

print("@array1\n");

This program produces the following output:


0 1 2 3 AA 5 6 BB 8 9 10

An array slice assignment is a quick and convenient way to swap two array elements from the same array.

Create an array with 10 elements.
Swap elements 4 and 7.
Print the array.

@array = (0..10);

@array[4, 7] = @array[7, 4];

print "@array\n";

This program produces the following output:


0 1 2 3 7 5 6 4 8 9 10

Notice that the 4th element and the 7th element have swapped places. You can also use the range operator when using array slice assignment.

Create an array with 10 elements.
Assign the 23rd, 24th, and 25th elements from
@array2 to @array1 as elements 0, 1, and 2.
Print the array.

@array1 = (0..10);

@array2 = ("A".."Z");

@array1[1..3] = @array2[23..25];

print "@array1\n";

This program produces the following output:


0 X Y Z 4 5 6 7 8 9 10

Figure 4.2 shows a depiction of which array elements in @array2 are being assigned to which array elements in @array1.

Figure 4.2 : Assigning array elements using an array slice and the range operator.

If you need only certain elements from an array, you can use the array slice to select a new array in one step.

Create an array with 10 elements.
Assign the 2nd, 4th, and 6th elements from
@array2 to @array1 as elements 0, 1, and 2.
Print the arrays.

@array1 = ("A".."J");

@array2 = @array1[2, 4, 6];

print("@array1\n");

print("@array2\n");

This program produces the following output:


A B C D E F G H I J

C E G

Example: Assigning an Array to Scalar Variables

At times, you may want to take array elements and assign them to scalar variables. The ability is especially useful inside fuNCtions and you'll read about that usage in Chapter 5 "FuNCtions."

It's also useful when you want to make your code more readable. So, instead of referring to the 3rd element of an array as $array[3], you can refer to the value as $town or whatever variable name you use.

In this next example, we'll take an array that holds an address and separate the elements into four scalar variables.

Create an array with Tom Jones' address.
Assign each element of the array to a separate scalar variable.
Print the scalar variables.

@array = ("Tom Jones", "123 Harley Lane", "Birmingham", "AR");

($name, $street, $town, $state) = @array;

print("$name, $street, $town, $state\n");

This program prints:


Tom Jones, 123 Harley Lane, Birmingham, AR

The first element of @array is assigned to the first scalar on the left side of the assignment operator. Because the scalars are surrounded by parentheses, Perl sees them as another list. If you couldn't do this type of multiple array element to multiple scalar assignment, you would have to do this:


@array = ("Tom Jones", "123 Harley Lane", "Birmingham", "AR");

$name   = $array[0];

$street = $array[1];

$town   = $array[2];

$state  = $array[3];

print("$name, $street, $town, $state\n");

I think that the first example is easier to understand, don't you? If the array has more elements than scalars, the extra elements are ignored. Conversely, if there are not enough elements, some of the scalar variables will have an undefined value.

Tip
You can also use the array slice and range operators with this type of assignment.

Order of PrecedeNCe

We briefly touched on the order of precedeNCe coNCept at the beginning of the chapter. Now that you are familiar with most of Perl's operators, we can explore the subject in more detail. Table 4.12 is an exhaustive list of operators and how they rank in terms of precedeNCe-the higher the level, the higher their precedeNCe. Operators at the same level have the same precedeNCe and are evaluated from left to right. Otherwise, higher precedeNCe levels are evaluated first.

Perl uses associativity to decide which operators belong together. For instaNCe, the unary minus operator has an associativity of right to left because it affects the operand immediately to its right.

Table 4.12  The Order of PrecedeNCe and Associativity for Perl Operators

Level
Operator
DescriptionAssociativity
22
(), [], {}
FuNCtion Calls, Parentheses, Array subscripts Left to right
21
->
Infix derefereNCe OperatorLeft to right
20
++, --
Auto iNCrement, Auto decrementNone
19
**
ExponentiationRight to left
18
!, ~, +,+, -,\
Logical not, bitwise not, unary plus, unary minus, refereNCe Right to left
17
=~, !~
Match, Not matchLeft to right
16
*, /, % x
Multiply, Divide, Modulus, Repetition Left to right
15
+, -,.
Add, Subtract, String coNCatenationLeft to right
14
<<,>>
Bitwise left shift, Bitwise right shift Left to right
13
 
File test OperatorsNone
12
 
Relational OperatorsNone
11
 
Equality OperatorsNone
10
&
Bitwise andLeft to right
9
|, ^
Bitwise or, Bitwise xorLeft to right
8
&&
Logical andLeft to right
7
||
Logical orLeft to right
6
..
Range OperatorNone
5
?:
Ternary or conditional OperatorRight to left
4
 
Assignment OperatorsRight to left
3
,
Comma OperatorLeft to right
2
not
Low precedeNCe logical OperatorsLeft to right
1
and
Low precedeNCe logical OperatorsLeft to right
0
or, xor
Low precedeNCe logical OperatorsLeft to right

Operators that are not discussed in this chapter are discussed elsewhere in this book. Table 4.1, at the beginning of the chapter, points out where you can get more information on those operators. In addition, you can read about the low precedeNCe logical operators in Chapter 13, "Handling Errors and Signals."

Example: Order of PrecedeNCe

While it is not possible to show examples of all the ramifications of operator precedeNCe, we can look at one or two so that you can get a feel for the coNCept.

First, an example using the ternary operator and various arithmetic operators:

Assign values to $firstVar and $secondVar.
Assign either a 1 or 0 to
$totalPages based on the evaluation of the condi-tion 34 + $firstVar-- + $secondVar ? 1 : 0.
Print
$totalPages.

$firstVar = 4;

$secondVar = 1;

$thirdVar = 34 + $firstVar-- + $secondVar ? 1 : 0;

print("$thirdVar\n");

The program produces the following output:


1

The ternary operator has a precedeNCe level of 5; every other operator has a higher precedeNCe level and will be evaluated first.

Assign values to $firstVar and $secondVar.
Assign either a 1 or 0 to
$thirdVar based on the evaluation of the condition 34 + $firstVar-- + ($secondVar ? 1 : 0).
Print $thirdVar.

$firstVar = 4;

$secondVar = 1;

$thirdVar = 34 + $firstVar-- + ($secondVar ? 1 : 0);

print "$thirdVar\n";

The program produces the following output:


39

This program results in a value of 39 for $thirdVar because the parentheses operators have a precedeNCe level of 22. They serve to isolate regions of the statements and tell Perl to evaluate the stuff inside before evaluating the rest of the statement.

Caution
Remember that these examples are contrived to show a point. I don't program in this manner. I recommend using parentheses to tell Perl exactly how you want your code to be evaluated. So, I would normally do the following:
$thirdVar = 34 + $firstVar + ($secondVar ? 1 : 0);
$firstVar--;
The decrementing of $firstVar has been pulled out of the first line because using the post-decrement operator has no effect on the first line and makes it harder to understand.

Here is a example of operator precedeNCe using the exponentiation operator. This also shows you how to determine operator precedeNCe on your own.

Assign an expression to $firstVar.
Assign an expression to
$secondVar using parentheses to indicate a preferred precedeNCe order.
Assign an expression to
$thirdVar using parentheses in a different manner to indicate a preferred precedeNCe order.
Print the variables.

$firstVar = -2 ** 4;

$secondVar = -(2 ** 4);

$thirdVar = (-2) ** 4;



print "$firstVar\n";

print "$secondVar\n";

print "$thirdVar\n";

The program produces the following output:


-16

-16

16

From this example, you can see the precedeNCe level for exponentiation is higher than unary minus because the first and second variables are equal.

Tip
If you always use parentheses to indicate how you want the operators to be evaluated, you'll never need to worry about operator precedeNCe in your code.

Summary

This chapter was pretty long and you've seen quite a few examples of how operators can be used. Let's review.

You learned that operators are used to telling Perl what actions to perform. Some operators take precedeNCe over others so that they and their operands will be evaluated first. An operand can be as simple as the number 10 or very complex-involving variables, literals, and other operators. This means that they are recursive in nature.

Perl has many different types of operators: arithmetic, assignment, binding, bitwise, comma, file test, list, logical, postfix, range, refereNCe, relational (both numeric and string), string, and ternary. Most of these operator types were discussed in this chapter, and the rest are scattered throughout the rest of the book. Table 4.1 lists the chapters where more information can be found on those operators not covered in this chapter.

The bulk of the chapter talked about various types of operators. Starting with binary arithmetic operators, and then unary arithmetic operators. You were introduced to the pre- and post-iNCrement and pre- and post-decrement operators. Next, came the logical operators and the bitwise operators. Sometimes, the bitwise shift operators are used when fast integer multiplication and division are needed.

Then, came numeric and string relational operators, followed by the ternary operator. The ternary operator was used to show you what an lvalue is. An lvalue is the value on the left side of an assignment operator. It must evaluate to some variable that Perl can use to hold a value.

The range operator was used to create sequential elements of an array, the coNCatenation operator was used to join two strings together, and the string repetition operator was used to repeat a string a given number of times.

Then, you looked at the list of assignment operators. Most were shortcuts to reduce typing and clarify the meaning of the assignment.

Finally, you saw a detailed list of Perl's operators and their order of precedeNCe. Several examples were given to illustrate how precedeNCe worked. My recommendation is to use parentheses to explicitly tell Perl how and in which order to evaluate operators.

The next chapter, "FuNCtions," will look at how fuNCtions and list operators are the same thing. You will be introduced to subroutines and parameters.

Review Questions

Answers to Questions are in Appendix A.

  1. What are three arithmetic operators?
  2. What does the x operator do?
  3. What does it mean to pre-decrement a variable?
  4. What is the value of 1 ^ 1?
  5. What is the value of 1 << 3?
  6. What is the ternary operator used for?
  7. Can the x operator be used with arrays?
  8. What is the precedeNCe level of the range operator?
  9. What is the value of 2 ¥ 5 + 10?
  10. What is the value of 65 >> 1?
  11. What is the spaceship operator used for?
  12. If an array were defined with ("fy".."gb"), what would its elements be?

Review Exercises

  1. Assign a value to $firstVar, using both division and subtraction.
  2. Using the post-decrement operator, subtract one from $firstVar.
  3. Write a program that assigns values to $firstVar and $secondVar and uses the >= operator to test their relationship to each other. Print the resulting value.
  4. Use the **= assignment operator to assign a value to $firstVar.
  5. Use the ternary operator to decide between two different values.
  6. Write a program that assigns values to $firstVar and $secondVar and uses the <=> operator to test their relationship to each other. Print the resulting value.
  7. Use the coNCatenation operator to join the following values together: "A" x 4 and "B" x 3.
  8. Use the exponentiation operator to find the value of 2 to the 5th power.
  9. Write an assignment statement that uses the && and || and ! operators.
  10. Write a program that prints the value of the fifth bit from the right in a scalar variable.
  11. Write a program that uses a bitwise assignment to set the fifth bit from the right in a scalar variable.
  12. Write a program that shows the differeNCe in operator precedeNCe between the % operator and the && operator.