As we alluded to earlier, Perl is also a mathematical language. This is true at several levels, from low-level bitwise logical operations, up through number and set manipulation, on up to larger predicates and abstractions of various sorts. And as we all know from studying math in school, mathematicians love strange symbols. What's worse, computer scientists have come up with their own versions of these strange symbols. Perl has a number of these strange symbols too, but take heart, most are borrowed directly from C, FORTRAN, sed (1) or awk (1), so they'll at least be familiar to users of those languages.
Perl's built-in operators may be classified by number of operands into unary, binary, and trinary operators. They may be classified by whether they're infix operators or prefix operators. They may also be classified by the kinds of objects they work with, such as numbers, strings, or files. Later, we'll give you a table of all the operators, but here are some to get you started.
Yes, we left subtraction and division out of Table 1.2 . But we suspect you can figure out how they should work. Try them and see if you're right. (Or cheat and look in the index.) Arithmetic operators are evaluated in the order your math teacher taught you (exponentiation before multiplication, and multiplication before addition). You can always use parentheses to make it come out differently.
There is also an "addition" operator for strings that does concatenation.
Unlike some languages that confuse this with numeric addition, Perl defines a
separate operator (
$a = 123; $b = 456; print $a + $b; # prints 579 print $a . $b; # prints 123456
$a = 123; $b = 3; print $a * $b; # prints 369 print $a x $b; # prints 123123123
These string operators bind as tightly as their corresponding arithmetic operators. The repeat operator is a bit unusual in taking a string for its left argument but a number for its right argument. Note also how Perl is automatically converting from numbers to strings. You could have put all the literal numbers above in quotes, and it would still have produced the same output. Internally though, it would have been converting in the opposite direction (that is, from strings to numbers).
A couple more things to think about. String concatenation is also implied by the interpolation that happens in double-quoted strings. When you print out a list of values, you're also effectively concatenating strings. So the following three statements produce the same output:
print $a . ' is equal to ' . $b . "\n"; # dot operator print $a, ' is equal to ', $b, "\n"; # list print "$a is equal to $b\n"; # interpolation
Which of these you use in any particular situation is entirely up to you.
The x operator may seem relatively worthless at first glance, but it is quite useful at times, especially for things like this:
print "-" x $scrwid, "\n";
which draws a line across your screen, presuming your screen width
Although it's not exactly a mathematical operator, we've already made
extensive use of the simple assignment operator,
Like the operators above, assignment operators are binary infix operators, which means they have an operand on either side of the operator. The right operand can be any expression you like, but the left operand must be a valid lvalue (which, when translated to English, means a valid storage location like a variable, or a location in an array). The most common assignment operator is simple assignment. It determines the value of the expression on its right side, and sets the variable on the left side to that value:
$a = $b; $a = $b + 5; $a = $a * 3;
Notice the last assignment refers to the same variable twice; once for the computation, once for the assignment. There's nothing wrong with that, but it's a common enough operation that there's a shortcut for it (borrowed from C). If you say:
lvalue operator= expression
it is evaluated as if it were:
lvalue = lvalue operator expression
except that the lvalue is not computed twice. (This only makes a difference if evaluation of the lvalue has side effects. But when it does make a difference, it usually does what you want. So don't sweat it.)
So, for example, you could write the above as:
$a *= 3;
which reads "multiply
$line .= "\n"; # Append newline to $line. $fill x= 80; # Make string $fill into 80 repeats of itself. $val ||= "2"; # Set $val to 2 if it isn't already set.
Line 6 of our grade example contains two string concatenations, one
of which is an assignment operator. And line 14 contains a
Regardless of which kind of assignment operator you use, the final value is returned as the value of the assignment as a whole. (This is unlike, say, Pascal, in which assignment is a statement and has no value.) This is why we could say:
chop($number = <STDIN>);
and have it chop the final value of
If you place one of the auto operators before the variable, it is known as a pre-incremented (pre-decremented) variable. Its value will be changed before it is referenced. If it is placed after the variable, it is known as a post-incremented (post-decremented) variable and its value is changed after it is used. For example:
$a = 5; # $a is assigned 5 $b = ++$a; # $b is assigned the incremented value of $a, 6 $c = $a--; # $c is assigned 6, then $a is decremented to 5
Line 15 of our grade example increments the number of scores by one, so
that we'll know how many scores we're averaging the grade over. It uses
a post-increment operator (
Logical operators, also known as "short-circuit" operators, allow the program to make decisions based on multiple criteria, without using nested conditionals. They are known as short-circuit because they skip evaluating their right argument if evaluating their left argument is sufficient to determine the overall value.
Perl actually has two sets of logical operators, a crufty old set borrowed from C, and a nifty new set of ultralow-precedence operators that parse more like people expect them to parse, and are also easier to read. (Once they're parsed, they behave identically though.) See Table 1.4 for examples of logical operators.
Since the logical operators "short circuit" the way they do, they're often used to conditionally execute code. The following line (from our grade example) tries to open the file grades .
open(GRADES, "grades") or die "Can't open file grades: $!\n";
If it opens the file, it will jump to the next line of the program. If it can't open the file, it will provide us with an error message and then stop execution.
Literally, the above message means "Open grades or die!" Besides being another example of natural language, the short-circuit operators preserve the visual flow. Important actions are listed down the left side of the screen, and secondary actions are hidden off to the right. (The $! variable contains the error message returned by the operating system - see "Special Variables" in Chapter 2 ). Of course, these logical operators can also be used within the more traditional kinds of conditional constructs, such as the if and while statements.
Comparison, or relational, operators tell us how two scalar values
(numbers or strings) relate to each other. There are two sets of
operators - one does numeric comparison and the other
does string comparison. (In either case, the arguments will be "coerced"
to have the appropriate type first.)
The file test operators allow you to test whether certain file attributes are set before you go and blindly muck about with the files. For example, it would be very nice to know that the file /etc/passwd already exists before you go and open it as a new file, wiping out everything that was in there before. See Table 1.6 for examples of file test operators.
Here are some examples:
-e "/usr/bin/perl" or warn "Perl is improperly installed\n"; -f "/vmunix" and print "Congrats, we seem to be running BSD Unix\n";
Note that a regular file is not the same thing as a text file. Binary files like /vmunix are regular files, but they aren't text files. Text files are the opposite of binary files, while regular files are the opposite of irregular files like directories and devices.
There are a lot of file test operators, many of which we didn't list. Most of the file tests are unary Boolean operators: they take only one operand, a scalar that evaluates to a file or a filehandle, and they return either a true or false value. A few of them return something fancier, like the file's size or age, but you can look those up when you need them.