2.1.3 Operators

An operator is usually thought of as denoting a function that takes one or two arguments. Operators can be unary or binary. An example of a unary operator is the - sign when it stands for negative. For example, -9 is negative 9. Another unary operators is not that stands for logical negation. Binary operators are written using the infix notation in Perl. In other words, the operator is written in between the two operands. For example, in 2 + 3, + is the binary addition operator written between two operands 2 and 3. There are many binary operators. A lot of them are from arithmetic that we know from school.
2.1.3.1 Arithmetic Operators and Expressions
An arithmetic expression consists of operators, operands, parentheses and function calls. We will discuss function calls in Chapter 12. An arithmetic operator takes one or two operands. The list of arithmetic operators provided by Perl is given Table 2.2.

Table 2.2: Arithmetic Operators

Of the operators shown in Table 2.2, + and - can be unary as well as binary. When used as unary, they signify the sign of a number. The auto-increment and auto-decrement operators are unary as well. Every other operator listed in Table 2.2 is binary. The ++ and -- operators are discussed in Section 2.7. The range operator produces the list of numbers from a start point to an end point incremented by 1. Thus, 1..10 when used in a list context produces the following list.

(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

The following program shows the use of several numeric operators.
Program 2.2

#!/usr/bin/perl
#file simpleArith.pl

use strict;
my ($a, $b, @c);
$a = 20;
$b = 30.5;

print '$a + $b = ', $a + $b, "\n";
print '$a - $b = ', $a - $b, "\n";
print '$a * $b = ', $a * $b, "\n";
print '$b / $a = ', $b / $a, "\n";
print '$b ** $a = ', $b ** $a, "\n";
print '$b % $a = ', $b % $a, "\n";
@c = $a .. $b;
print '$a .. $b = ', "@c", "\n";

The program simply prints the obvious result of applying the arithmetic operators. The output of this program is given below.

$a + $b = 50.5
$a - $b = -10.5
$a * $b = 610
$b / $a = 1.525
$b ** $a = 4.85284909839324e+29
$b % $a = 10
$a .. $b = 20 21 22 23 24 25 26 27 28 29 30

The remainder operator prints its result in integer form after truncating any digits after the decimal point. The range operator produces a list @c that is printed later. When a list is input or typed, the elements are enclosed within parentheses. The parentheses are not printed when a list is output using the print statement. By default, when a list is interpolated inside a doubly-quoted string, any two contiguous elements are separated by a blank space. Otherwise, the output is self-explanatory.
2.1.3.2 String Operators
The string scalars have several operators. Three useful operators are listed in Table 2.3.
Table 2.3: String Operators

All three operators shown in Table 2.3 are binary. Thus,

"Justin O'Malley,\t" . "Christopher Paul\n"

produces the single string

"Justin O'Malley,\tChristopher Paul\n"

by putting them together or concatenating them. The x operator takes a string operand on the left and causes the string to be repeated the number of times indicated by the second operand to produce a longer string. Thus,

"_" x 50

produces

__________________________________________________

by repeating the underscore 50 times. This is sometimes useful when we want to print nice-looking tables or lines indicating boundaries among parts of a large printed output. The range operator, used in the list context, produces a list of the intervening elements. Thus,

'a'..'f'

produces the list given below.

('a', 'b', 'c', 'd', 'e', 'f')

The following program shows the use of a few string operators.
Program 2.3

#!/usr/bin/perl
#file simpleString.pl

my ($justin, $chris, @list);
$justin = "Justin O'Malley, and ";
$chris = "Christopher Paul";

print '$justin . $chris = ', $justin . $chris, "\n";
print '$justin x 2 . $chris = ', $justin x 2 . $chris, "\n";
@list = aa .. au;
print 'aa .. au = ', "@list\n";

The output of this program is very easy to understand and is given below. A long line of output has been broken into to two for printing purposes.

$justin . $chris = Justin O'Malley, and Christopher Paul
$justin x 2 . $chris = Justin O'Malley, and Justin O'Malley, and
Christopher Paul
aa .. au = aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at au

The range operator produces all the intervening two-character strings between aa and au.
2.1.3.3 When is a scalar true or false?
A scalar can be a string, a number or a reference. A string scalar is considered false if it is the empty string or the string containing just a zero, i.e., the single character string "0". Thus, there are only two string values that are considered false. The empty string is written as "" or ''. Any other string is considered true. Thus, the string "000" or "0.00" are considered true because neither is exactly the string "0". To evaluate a numeric scalar for truth or falsehood, it is first coerced to a string. The numeric value 0 is always coerced into the single character "0", even if the numeric zero is written with more that one digits, with a decimal point, or as the result of an expression. Thus, the number 0.00 is converted to the string "0". Thus, 0 or 000 or 10-10 are considered false because when coerced into a string, they all become the single character string "0". Anything that is not considered false is considered true. Any undefined value is considered false. The rules are explicitly the following [WCS96]:
1. Any string is true except for "" and ''.
2. Any number is true except 0.
3. Any reference is true. We have not seen references yet. A reference refers to the address of a variable, data or a subroutine.
4. An undefined value is false. There are situations in which the value of a variable can be undefined.
Whether a scalar is evaluated true or false has important implications when writing statements that are executed conditionally, or that are executed iteratively based on whether a conditional expression is true or false.
2.1.3.4 Comparison or Relational Operators
An operator that compares two parameters is a relational operator. There are arithmetic relational operators and string relational operators. Perl’s relational operators are listed in Table
2.4. The operators are obvious except the three-way comparison operators <=> and cmp. <=> takes two numeric operands and returns -1, 0 or 1, depending upon whether the first operand is less than, or equal to, or greater than the second operand. <=> is called the ship operator by some. cmp is similar except that it treats the two arguments given to it as string and compares them alphabetically and not as numbers.
Table 2.4: Numeric and String Comparison Operators

The following program shows the use of a few numeric relational operators.
Program 2.4

#!/usr/bin/perl
#file arithCondition.pl

my ($a, $b, $result);
$a = 20;
$b = 30;
$result = $a > $b;
print "result = $result\n";
$result = $a < $b;
print "result = $result\n";
$result = $a == $b;
print "result = $result\n";
$result = $a <=> $b;
print "result = $result\n";

Relational operators are not usually used like the way they are in this program where we assign scalar variables with the result returned by them. Normally, relational expressions formed by using relational operators are used in conditional statements and loops to control the number of iterations. Here, we assign scalar variables to the result of applying relational operators in order to simply illustrate how they work. Consider the statement given below.

$result = $a > $b;

The value of $a is 20 and $b is 30. Therefore, $a > $b is false. The relational operator returns the empty string as the value of $a > $b. Thus, $result gets the value empty string. However, in the statement

$result = $a < $b;

$a < $b is true, and the < operator returns "1" in this case. Any non-zero string or any string that is not empty is considered true, but Perl decides to return "1" for simplicity. The <=> or the ship operator returns -1 because the first argument $a is less than the second argument $b.
The output of this program is given below.

result =
result = 1
result =
result = -1

The first result is printed as nothing because the value of $result is the empty string in this case.
The following program shows the use of a few string relational operators: eq, lt and cmp.
Program 2.5

#!/usr/bin/perl
#file stringCond.pl
use strict;

my ($justin1, $justin2, $result);
$justin1 = "Justin O'Malley";
$justin2 = "Justin Paul";
$result = $justin1 eq $justin2;
print "result = $result\n";
$result = $justin1 lt $justin2;
print "result = $result\n";
$result = $justin1 cmp $justin2;
print "result = $result\n";

The output of running this program is given below.

result =
result = 1
result = -1

Once again, false is returned by an operator as an empty string and true as the string "1". cmp returns -1 since Justin O'Malley is alphabetically before Justin Paul.
2.1.3.5 Logical Operators
Logical operators allow one to combine results of several true or false results. The logical operators available in Perl are given in Table 2.5.
Table 2.5: Logical Operators
There are two versions to each operator. The difference between the two is that one version is of much lower precedence. The lower precedence operators are there so that individual complex expressions that are put together using the operators need not be parenthesized much. The following program shows the use of these logical operators.
Program 2.6

#!/usr/bin/perl
#file logical.pl

use strict;
my ($a, $b, $c, $d, $result);
$a = 20;
$b = 30;
$c = 40;
$d = 50;

$result = not ($a > $b);
print "result = $result\n";
$result = ! ($a > $b);
print "result = $result\n";
$result = ($a > $b) or ($b > $c) or ($c > $d);
print "result = $result\n";
$result = ($a > $b) || ($b > $c) || ($c > $d);
print "result = $result\n";
$result = ($b > $a) or ($c > $b) || ($d > $c);
print "result = $result\n";
$result = ($b > $a) and ($c > $b) and ($d > $c);
print "result = $result\n";
$result = ($b > $a) && ($c > $b) && ($d > $c);
print "result = $result\n";
$result = (($b > $a) or ($c > $b)) && ($d > $c);
print "result = $result\n";

The output of the program is given below.

result = 1
result = 1
result =
result =
result = 1
result = 1
result = 1
result = 1

Obviously or and || can be used interchangeably in many situations. So can and and &&. Also, not and ! can be used interchangeably. Once again, false is returned as an empty string while true is returned as the string "1". Obviously, the empty string is printed as nothing.
2.1.3.6 Operator Precedence
When we have have an expression with more than one operator, its semantics may not be easily understood unless we know the order of computation. For example, in the expression

$a + $b + $c + $d

we may like to know the order in which the computation is performed, whether from left to right, or right to left, or in some other order. In this case, we have the same operator + repeated several times. The + operator is left associative. This means that the leftmost + operator is evaluated first before the second + which is evaluated before the third +, etc. Therefore, the expression given is equivalent to the following fully parenthesized expression.

(($a + $b) + $c) + $d

Of course, we have assumed that all four variables are numeric scalars. There are some operators that are right associative, e.g., the exponentiation operator: **. So,

$a ** $b ** $c ** $d

actually means

$a ** ($b ** ($c ** $d))

where pairs of operators are parenthesized from the right end. Thus,

2 ** 3 ** 4

means 2(34)=281=2417851639229258349412352 and not (23)4=84=4096. For every operator in Perl, the designers of the language specify its associative nature. The arithmetic operators follow normal rules of arithmetic, but with the others, the designers are more free to choose.
Associativity rules apply when we have the same operator repeated several times in an expression. We may have several distinct but contiguous operators as well, but these operators must have the same precedence for associative rules to apply. Each operator has a precedence number associated with it although it is not necessary to know what it is. Normally, it suffices to know how the operators are ranked considering precedence. When several operators appear in an expression, the highest precedence operator is performed first, next the operator with the second highest precedence, and so on. For example,

$a + $b ** $c

is evaluated as if it were parenthesized as

$a + ($b ** $c)

and not

($a + $b) ** $c

because * has higher priority than + and thus, * is evaluated first. All precedence and associative rules can be dispensed with if we explicitly and completely parenthesize an expression. The associativity and precedence of some common Perl operators are given in Table 2.6. One is advised to use parentheses liberally even if there is the slightest doubt in writing an expression. Operators within the same horizontal grouping in Table 2.6 have the same precedence. When several such operators are used in succession in an expression, associativity rules apply. Several operators are specified as non-associative. For such operators, exclusive parenthesization is necessary if used several times in an expression in succession. An example of a list operator or function is the command for opening files: open because it takes a list of two arguments: a filehandle name and a file name.

Table 2.6: Associativity and Precedence of Operators