Chapter 6. Where’s the Operator?

Image

In the real world, there are operators who operate switchboards, computers, bulldozers, tanks, and so forth. In Perl, operators operate on numbers and strings, or a combination of them. Operators are symbols, such as +, -, =, >, <, that produce a result based on some rules. This chapter is all about Perl operators, their use, and their rules.

By the end of this chapter, you should be able to explain how Perl evaluates the following example:

$year=(localtime)[5] + 1900;
$year % 100 == 0 && $year % 400 == 0 || $year % 100 != 0 &&
$year % 4 == 0? printf "Year %d is leap year. ",$year :
                printf " Year %d is not a leap year. ", $year;

6.1 About Perl Operators—More Context

Before getting into the nitty gritty of Perl operators, consider the following Example 6.1. The user is asked a question and his answer is tested. The results would normally be unexpected unless you have a good grasp on how Perl operators handle context, a subject we have been discussing from the beginning. The problem with this example is the use of the == operator, the equality operator used to test whether two numbers are equal. But in the example, the operators are used incorrectly to evaluate the equality of two strings.

Now we will add one line to the program in Example 6.1. The warnings pragma will warn you that the = = operator expects numeric data, and $answer is not numeric.

6.1.1 Evaluating an Expression

A Perl operator manipulates data items called operands; for example, 5 and 4 are operands in the expression 5 + 4. Operators and operands are found in expressions. An expression combines a group of values and returns something. A statement tells the computer to do something; for example:

$n = 5 + 4;

gets the return value from the expression 5 + 4 and assigns it to $n. Perl statements end with a semicolon.

In the numeric expression, 5 + 4 - 2, three numbers are combined. The operators are the + and - signs. The operands for the + sign are 5 and 4. After that part of the expression is evaluated to 9, the expression becomes 9 - 2. After evaluating the complete expression, the result is 7.

Because the plus and minus operators each manipulate two operands, they are called binary operators. If there is only one operand, the operator is called a unary operator; and if there are three operands, it is called a ternary operator. We’ll see examples of these operators later in the chapter.

Most of the Perl operators are borrowed from the C language, although Perl has some additional operators of its own.

6.2 Mixing Types

As Example 6.3 demonstrates, if you have operands of mixed types (that is, numbers and strings), Perl will make the appropriate conversion by testing whether the operator expects a number or a string for an operand. This is called coercion.

If the operator is a numeric operator, such as an arithmetic operator, and the operand(s) is a string, Perl will treat the string as a decimal floating-point value. Undefined values will become zero. If there is leading whitespace or trailing non-numeric characters, they will be ignored, and if a string cannot be converted to a number, it will be converted to zero. (See Table 6.1.)

$string1 = "5 dogs ";
$string2 = 4;
$number = $string1 + $string2;  # Numeric context
print "Number is $number. ";   # Result is 9

Image

Table 6.1 How Strings Are Converted to Numbers

Likewise, if Perl encounters a string operator and the operand(s) is numeric, Perl will treat the number as a string. The concatenation operator, for example, expects to join two strings together.

$number1 = 55;
$number2 = "22";
$string = $number1 . $number2;  # Context is string
print "String is $string. "     # Result is "5522"

6.3 Precedence and Associativity

Which piece has the higher precedence (most power) in a game of chess? The queen or the bishop? The bishop or the pawn? These pieces have rules on how they move across the board. In programming languages, a table of precedence (see Table 6.2) shows what operators are evaluated before others and whether the evaluation is from left to right or vice-versa.

Image
Image

Table 6.2 Precedence and Associativity (Highest to Lowest)

When an expression contains a number of operators and operands, and the result of the operation is potentially ambiguous, then the order of precedence and associativity determines how Perl will evaluate such an expression. Precedence refers to the way in which the operator binds to its operand. The multiplication operator binds more tightly to its operands than the addition operator, so it is of higher precedence; whereas the assignment operators are low in precedence and thus bind loosely to their operands. Parentheses are of the highest precedence and are used to control the way an expression is evaluated. When parentheses are nested, the expression contained within the innermost set of parentheses is evaluated first.

Associativity refers to the order in which a sequence of operators with the same precedence evaluates its operands: left to right, in no specified order, or right to left.

In the following example, how is the expression evaluated? Is addition, multiplication, or division done first? And in what order—right to left or left to right?

Table 6.2 summarizes the rules of precedence and associativity for the Perl operators. The operators on the same line are of equal precedence. The rows are in order of highest to lowest precedence.

6.3.1 Assignment Operators

The = sign is an assignment operator. The value on the right-hand side of the equal sign is assigned to the variable on the left-hand side. Table 6.3 illustrates assignment and shortcut assignment statements borrowed from the C language.

Image

Table 6.3 Assignment Operators

6.3.2 Boolean

Perl does not have a special Boolean type, true or false, but does use Boolean context when evaluating expressions. To quote the Perl documentation:

The number 0, the strings '0' and ", the empty list "()", and "undef" are all false in a Boolean context. All other values are true. Negation of a true value by "!" or "not" returns a special false value. When evaluated as a string, it is treated as "", but as a number, it is treated as 0.1

1. From perlsyn under “Truth and Falsehood,” http://perldoc.perl.org/perlsyn.html#Truth-and-Falsehood.

So what does that mean? Although Perl does not have specific Boolean types, every value in scalar context, if checked using if, will be either true or false.

if ($x == 10) {print "true ";}

if ($x){print "true ";}

The first example will check if the value $x is equal to 10 and if true, will return 1; if false, 0. If true, the block is entered.

The second example checks to see if $x itself is true or false; only false if it evaluates to 0, "0", the empty string or undef.

6.3.3 Relational Operators

Relational operators are used to compare operands. The result of the comparison is either 1 (true) or the empty string “ ” (false). Perl has two classes of relational operators: one set that compares numbers and another that compares strings. Normally, these operators are used to test a condition when using if/else loops, while loops, and so forth; for example:

if ( $x > $b ){ print "$x is greater. "; }

The expression (5 > 4 > 2) would have produced a syntax error because there is no associativity. (See Table 6.2.) We will discuss conditionals in more detail in Chapter 7, “If Only, Unconditionally, Forever.”

Numeric

Table 6.4 contains a list of numeric relational operators.

Image

Table 6.4 Relational Operators and Numeric Values

String

The string relational operators evaluate their operands (strings) by comparing the alphabetic value of each character in the first string with the corresponding character in the second string. The comparison (called lexagraphical ordering) includes trailing whitespace.

If the first string contains a character that is of a higher or lower alphabetic value than the corresponding character in the second string, the value 1 is returned; otherwise, the empty string or 0 is returned.

Table 6.5 contains a list of relational string operators.

Image

Table 6.5 Relational Operators and String Values

6.3.4 Conditional Operators

The conditional operator is another taken from the C language. It requires three operands and, thus, it is often called the ternary conditional operator. It is used to evaluate expressions, a shortcut for the if/else construct.

6.3.5 Equality Operators

The equality operators test numeric operands and string operands (see Tables 6.6 and 6.7). Be sure when you are testing equality that you use the string operators for strings and the numeric operators for numbers! If, for example, you have the expression

"5 cats" == "5 dogs"

Image

Table 6.6 Equality Operators and Numeric Values

Image

Table 6.7 Equality Operators and String Values

the expression will evaluate to true. Why? Because Perl sees a numeric operator, = =. The = = operator expects its operands to be numbers, not strings. Perl will then convert the “5 cats” to the number 5 (throwing away all non-numeric characters) and the string “5 dogs” to the number 5, resulting in 5 = = 5, which evaluates to true. In the conversion, Perl starts on the left-hand side of the string and looks for a number; if there is a number, Perl keeps it. As soon as a non-number is found, the conversion stops. If the string starts with a non-number, the result is 0.

Numeric

The numeric equality operators evaluate their operands (numbers) by comparing their numeric values. If the operands are equal, 1 (true) is returned; if the operands are not equal, 0 (false) is returned.

The numeric comparison operator evaluates its operands, returning a -1 if the first operand is less than the second operand, 0 if the numbers are equal, or 1 if the first operand is greater than the second.

String

The string equality operators evaluate their operands (strings) by comparing the ASCII value of each character in the first string with the corresponding character in the second string. The comparison includes trailing whitespace.

If the first string contains a character that is of a higher ASCII value than the corresponding character in the second string, the value 1 is returned; if the strings are equal, 0 is returned; if the first string character has a lesser ASCII value than the corresponding character in the second string, -1 is returned (see Table 6.7).

6.3.6 The Smartmatch Operator

As of Perl 5.10.1, the quirky smartmatch operator (still experimental) provides you a way to compare two operands without imposing context on them, as we saw in the previous section with = = and eq.

The smartmatch operator infers the type that should be used. According to the Perl documentation for Perl 5 version 18.2 at perldoc.perl.org, “The behavior of a smartmatch depends on what type of ‘things’ (scalars, arrays, hashes) its arguments are.”

For example, in the expression “yes” = = “no”, the = = operator forces numeric context, converting both “yes” and “no” to 0, because the = = takes only numeric values as its operands. The eq operator should have been used when testing the equality of two strings. But the smartmatch operator infers what the operands should be by how they are used. The smartmatch operator returns 1 if true, and “ ” if false.

The smartmatch operator also compares different types of operands, such as arrays, hashes, regular expressions, and so forth. To understand how this works, ask yourself, “Does the value on the left-hand side match the value on the right-hand side, and if the right-hand side is an array, does the value match any of the elements in the array? Or if the value on the right-hand side is a hash, does the value on the left match any of the keys in the hash?” The smaller thing is usually on the left-hand side of the ~~ and the larger thing on the right.

6.3.7 Logical Operators (Short-Circuit Operators)

The short-circuit operators evaluate their operands, from left to right, testing the truth or falsity of each operand, in turn. There is no further evaluation once a true or false condition is satisfied. Unlike C, the short-circuit operators do not return 0 (false) or 1 (true) but rather the value of the last operand evaluated. These operators are most often used in conditional statements. (See Chapter 7, “If Only, Unconditionally, Forever.”)

If the expression on the left-hand side of the && evaluates to false, the expression is false and that value is returned. If the expression on the left-hand side of the operator evaluates to true (nonzero), the right-hand side is evaluated and its value is returned.

The logical operators can also be represented as and, or, or not, but the precedence for them is lower. If the expression on the left-hand side of the || operator is evaluated as true (nonzero), the value of the expression is returned. If the value on the left-hand side of the || is false, the value of the expression on the right-hand side of the operator is evaluated, and its value is returned.

A list of logical operators is shown in Table 6.8.

Image

Table 6.8 Logical Operators (Short-Circuit Operators)

6.3.8 Logical Word Operators

These logical operators are of lower precedence than the short-circuit operators, but basically work the same way and make the program easier to read, and they also short-circuit. In addition to the short-circuit operators, the xor (exclusive or) operator has been added to the logical word operators.

6.3.9 Arithmetic Operators and Functions

Perl comes with the standard set of arithmetic operators found in most languages, plus some of its own. It also provides for a number of built-in functions for handling mathematical operations such as finding the square root of a number, producing random numbers, getting an absolute value, and so forth.

Arithmetic Operators

Perl’s arithmetic operators are listed in Table 6.9.

Image

Table 6.9 Arithmetic Operators

Arithmetic Functions

In addition to arithmetic operators, Perl provides a number of built-in functions to evaluate arithmetic expressions (see Table 6.10).

Image

Table 6.10 Built-in Perl Arithmetic Functions

There are also a number of general utility functions provided by CPAN in a module called List::Util, including first, max, maxstr, min, minstr, reduce, shuffle, and sum.2 Now this module is part of the standard Perl library. Type perldoc List::Util at your prompt and you will see the following output:

2. See http://perldoc.perl.org/List/Util.html#DESCRIPTION.

NAME

List::Util - A selection of general-utility list subroutines

SYNOPSIS

use List::Util qw(first max maxstr min minstr reduce shuffle sum);

DESCRIPTION

“List::Util” contains a selection of subroutines that people have expressed would be nice to have in the perl core, but the usage would not really be high enough to warrant the use of a keyword, and the size so small such that being individual extensions would be wasteful.

< Continues here>

Generating Random Numbers

When looking for a good description of random number generation on the Web, one of the related topics is Games>Gambling>Lotteries>Ticket Generators. Games and lotteries depend on the use of random number generation and so do more sophisticated programs, such as cryptographic protocols that use unpredictable encrypted keys to ensure security when passing information back and forth on the Web.

Random numbers produced by programs are called pseudo-random numbers. As described in an article by Ian Goldberg and David Wagner concerning Web security, truly random numbers can be found only in nature, such as the rate of decay of a radioactive element. Apart from using external sources, computers must generate these numbers themselves, but since computers are deterministic, these numbers will not be truly random. Perl programs that need to generate pseudo-random numbers can use the built-in rand function described next.

The rand/srand Functions

The rand function returns a pseudo-random fractional number between 0 and 1. If EXPR has a positive value, rand returns a fractional number between 0 and EXPR. The srand function sets the random number seed for the rand function but is no longer required if you are using a version of Perl greater than 5.004, which you should be. A seed is a random number itself that is fed to the random number generator as the starting number from which new random numbers are produced. The rand function is given a seed and, using a complex algorithm, produces random numbers within some range. If the same seed is fed to the rand function each time it is called, the same series of numbers will be produced. A different seed will produce a different series of random numbers. The default seed value used to be the time of day, but now a more unpredictable number is selected for you by Perl.

You may want to set the seed with srand(). For example, when performing simulations, you might use a different seed for each simulation and when a problem occurs, save the seed, and then reset that seed to reproduce the error.

6.3.10 Autoincrement and Autodecrement Operators

The autoincrement and autodecrement operators are taken straight from the C language The autoincrement operator adds 1 to the value of a variable, and the autodecrement operator subtracts 1 from the value of a variable. When used with a single variable, these operators are just shortcuts for the traditional method of adding and subtracting 1. However, if used in an assignment statement or if combined with other operators, the end result depends on the placement of the operator (see Table 6.11). Consider the following example:

$i = 4;
printf  "%d ", $i++;

printf "%d ", ++$i;

Image

Table 6.11 Autoincrement and Autodecrement Operators and Assignment

The first example is a post increment operation; that is, $i won’t be incremented until after its value is printed, resulting in 4 being printed.

Now if we set $i back to 4 and go to the second example, $i is pre-incremented before it is printed, resulting in 5.

Don’t use these operators unless you know what to expect. For example, the following statement is frivolous and the results are based on how the printf function internally evaluates its arguments:

$x = 5;
printf "%d  %d   %d   %d ", $x++, --$x, $x--, ++$x;

The most common use for these operators is within loops. It’s a quick way to add or subtract 1 from a value. See Example 6.23.

Image

Figure 6.1 Pre- and post-increment operators.

6.3.11 Bitwise Logical Operators

A Little Bit About Bits

People represent numbers in decimal, or base 10, a numbering system based on 10 values starting from 0 to 9; for example, $100,000 and 1955. The HTML color codes are represented in hexadecimal, base 16, values ranging from 0 to 15; for example, #00FFFF is cyan and #FF00FF is fuchsia.

Computers, on the other hand, store everything in binary, or base 2. A binary numbering system represents numbers in two values, 0 or 1. Each of the individual 1s and 0s are called bits. All the data you use is stored in your computer using bits. A byte is made up of 8 bits, a word is 2 bytes, or 16 bits, and finally, two words together are called a double word, or dword, which is a 32-bit value. The reason a computer uses only 0s and 1s for everything is because a binary digit is represented by the presence of an electric current. If the level of electricity reaches a certain level, the digit is 1. Otherwise, the digit is a 0. Using just two numbers makes building hardware less difficult and cheaper than if electrical levels were represented by a bigger combination of bits, like base 10 (decimal) or base 16 (hexadecimal). Hence, computers store everything in binary.

Bitwise Operators

Most processors today are built to operate on 32-bit numbers. For example, the term “Win32” is derived from the fact that an integer on a Win32 compiler defaults to 32 bits. Bitwise operators allow you to turn on or off specific bits within an integer. For example, if you are setting a read-only flag on a file, you need only two values, on or off, represented as 1 or 0. And if both the left- and right-hand parameters are strings, the bitwise operator will operate on the characters within the string.

Bitwise operators treat their operands as a set of 64 bits (0s and 1s), rather than as decimal, hexadecimal, or octal numbers. For example, the decimal number 9 has a binary representation of 1001. Although bitwise operators perform their operations on expressions containing bit strings, they return standard Perl numerical values, as shown in Table 6.13. If you are working with graphics, games, encryption, registers, setting switches, or any operation that requires “twiddling bits,” then the bitwise operators may become useful. Generally speaking, those types of operations are more fitting for such languages as C or Java.

When you’re ready to manipulate integer values at the bit level, the bitwise logical operators are used. The bitwise operators are binary operators and manipulate their operands in terms of the internal binary representation of those operands. A bit-by-bit comparison is made on each of the corresponding operands, producing its result as the binary value (see Tables 6.12 and 6.13).

Image

Table 6.12 Bitwise Logical Operators

Image

Table 6.13 Resulting Values of Bitwise Operators

6.3.12 Range Operator

The range operator is used in both scalar and array context. In a scalar context, the value returned is a Boolean, 1 or 0. In an array context, it returns a list of items starting on the left side of the operator and counting by ones until the value on the right-hand side is reached.

6.3.13 Special String Operators and Functions

A number of operations can be performed on strings. For example, the concatenation operator joins two strings together, and the string repetition operator concatenates as many copies of its operand as specified.

Perl also supports some special functions for manipulating strings (see Table 6.14). The substr function returns a substring found within an original string, starting at a character offset in the original string and ending with the number of character positions to the right of that offset. The index function returns the character offset of the first character of a substring found within the original string. The length function returns the number of characters in a given expression.

Image

Table 6.14 String Operations

6.4 What You Should Know

1. What is meant by the term operand?

2. How does Perl treat the expression “5cats” + 21?

3. How does Perl treat the expression 23 . 43?

4. What is an autoincrement operator?

5. What is a pseudorandom number?

6. What is the difference between eq and ==?

7. Are and and && the same?

8. What is the & operator?

9. What is a ternary operator?

10. How does Perl use relational operators to compare strings?

11. What is the difference between and and or?

12. Where is the equal sign in the precedence table?

13. Does the equal sign associate right to left or left to right?

14. What Perl string function lets you extract a piece of a string?

15. What function converts a string to uppercase?

16. What operator allows you to repeat a string?

17. What operator allows you to concatenate strings together?

6.5 What’s Next?

In the next chapter, we discuss the Perl control structures, how to test whether a condition is true or false with if and unless constructs, how to block statements, how to use loops to repeat a statement(s), and how to break out of loops, use labels, and nest loops.

Exercise 6: Operator, Operator

1. Use printf to print the average of three floating-point numbers with a precision of two decimal places.

2. What are two other ways you could write $x = $x + 1;?

3. Write the following expression using a shortcut: $y = $y + 5;

4. Calculate the volume of a room that is 12.5 ft. long, 9.8 ft. wide, and 10.5 ft. high. Square the number 15 and print the result.

5. How do the ~ ~, = =, and eq differ? Give an example of each.

6. What would the following program print?

$x = 15; $b = 4; $c = 25.0; $d = 3.0;
printf "4 + c / 4 * d = %f ", 4 + $c / 4 * $d;
printf "x / d * x + c = %.2f ", $x / $d * $x + $c;
printf "%d ", $result = $c / 5 - 2;
printf "%d = %d + %f ", $result = $b + $c, $b, $c;
printf "%d ", $result == $d;

7. Given the values of $x=10, $b=3, $c=7, and $d=20, print the value of $result:

$result = ( $x >= $b ) && ( $c < $d ); print "$result ";
$result = ( $x >= $b ) and ( $c < $d ); print "$result ";
$result = ( $x < $b) || ( $c <= $d ); print "$result ";
$result = ( $x < $b) or ( $c <= $d ); print "$result ";
$result = $x % $b;

8. Write a program called convert that converts a Fahrenheit temperature to Celsius using the following formula: C = ( F - 32 ) / 1.8

9. Create an array of five sayings:

“An apple a day keeps the doctor away”

“Procrastination is the thief of time”

“The early bird catches the worm”

“Handsome is as handsome does”

“Too many cooks spoil the broth”

Each time you run your script, a random saying will be printed. Hint: the index of the array will hold a random number.

10. What’s wrong with this statement?

$x = 5;
$y = 13;
$z = 3;
print  ($x + $y) / $z;

Turn on warnings. What is the meaning of the warning?

11. The following formula is used to calculate the fixed monthly payment required to fully amortize a loan over a term of months at a monthly interest rate. Write a Perl expression to represent the following formula where: P = principal amount borrowed, r = periodic interest rate (annual interest rate divided by 12), n = total number of payments (for a 30-year loan with monthly payments, n = 30 years × 12 months = 360), and A = periodic payment.

Image

12. At the start of this chapter, there was an example that calculates whether or not this is a leap year. In your browser’s search box, type the following:

How do I determine a leap year--Perl monks

You can download their example and test it. The Perl monks are devoted to answering questions related to Perl and offer many solutions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.198.174