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.
The rest of you can take comfort in knowing that, by learning all these strange symbols in Perl, you've given yourself a head start on all those other strange languages.
Perl's built-in operators may be classified by number of operands into unary, binary, and trinary (or ternary) operators. They may be classified by whether they're prefix operators (which go in front of their operands) or infix operators (which go in between their operands). 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 first here are some handy ones to get you started.
Arithmetic operators do what you would expect from learning them in school. They perform some sort of mathematical function on numbers. For example:
Example | Name | Result |
---|---|---|
$a + $b | Addition | Sum of $a and
$b |
$a * $b | Multiplication | Product of $a and
$b |
$a % $b | Modulus | Remainder of $a divided by
$b |
$a ** $b | Exponentiation | $a to the power of
$b |
Yes, we left out subtraction and division—we suspect you can figure out how they should work. Try them and see if you're right. (Or cheat and look in Chapter 3.) Arithmetic operators are evaluated in the order your math teacher taught you (exponentiation before multiplication; multiplication before addition). You can always use parentheses to make it come out differently.
There is also an "addition" operator for strings that performs concatenation (that is, joining strings end to end). Unlike some languages that confuse this with numeric addition, Perl defines a separate operator (.) for string concatenation:
$a = 123; $b = 456; print $a + $b; # prints 579 print $a . $b; # prints 123456
There's also a "multiply" operator for strings,
called the repeat operator. Again, it's a
separate operator (x
) to keep it distinct from
numeric multiplication:
$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. And 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. (But bear in mind that interpolation is often the most readable.)
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
$scrwid
contains your screen width, and not your
screw identifier.
Although it's not exactly a mathematical operator,
we've already made extensive use of the simple assignment operator,
=
. Try to remember that =
means "gets set to" rather than "equals". (There is also a
mathematical equality operator ==
that means
"equals", and if you start out thinking about the difference between
them now, you'll save yourself a lot of headache later. The
==
operator is like a function that returns a
Boolean value, while =
is more like a procedure
that is evaluated for the side effect of modifying a
variable.)
Like the operators described earlier, 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 then 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 previous example as:
$a *= 3;
which reads "multiply $a
by 3". You can do
this with almost any binary operator in Perl, even some that you
can't do it with in C:
$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 "true".
Line 6 of our Average Example[16] 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 of the variable on the left is returned as the value of the assignment as a whole.[17] This will not surprise C programmers, who will already know how to use this idiom to zero out variables:
$a = $b = $c = 0;
You'll also frequently see assignment used as the condition of
a while
loop, as in line 4 of our average
example.
What will surprise C programmers is that assignment in Perl returns the actual variable as an lvalue, so that you can modify the same variable more than once in a statement. For instance, you could say:
($temp -= 32) *= 5/9;
to do an in-place conversion from Fahrenheit to Celsius. This is also why earlier in this chapter we could say:
chop($number = <STDIN>);
and have it chop the final value of
$number
. Generally speaking, you can use this
feature whenever you want to copy something and at the same time do
something else with it.
As if $variable += 1
weren't short
enough, Perl borrows from C an even shorter way to increment a
variable. The autoincrement (and autodecrement) operators simply add
(or subtract) one from the value of the variable. They can be placed
on either side of the variable, depending on when you want them to
be evaluated:
If you place one of these "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 Average Example increments the number of scores
by one, so that we'll know how many scores we're averaging. It uses
a post-increment operator ($scores++
), but in
this case it doesn't matter, since the expression is in a void
context, which is just a funny way of saying that the expression is
being evaluated only for the side effect of incrementing the
variable. The value returned is being thrown away.[18]
Logical operators, also known as "short-circuit"
operators, allow the program to make decisions based on multiple
criteria without using nested if
statements. They
are known as short-circuit operators because they skip (short
circuit) the evaluation of their right argument if they decide the
left argument has already supplied enough information to decide the
overall value. This is not just for efficiency. You are explicitly
allowed to depend on this short-circuiting behavior to avoid
evaluating code in the right argument that you know would blow up if
the left argument were not "guarding" it. You can say "California or
bust!" in Perl without busting (presuming you do get to
California).
Perl actually has two sets of logical operators, a traditional set borrowed from C and a newer (but even more traditional) set of ultralow-precedence operators borrowed from BASIC. Both sets contribute to readability when used appropriately. C's punctuational operators work well when you want your logical operators to bind more tightly than commas, while BASIC's word-based operators work well when you want your commas to bind more tightly than your logical operators. Often they work the same, and which set you use is a matter of personal preference. (For contrastive examples, see Section 3.20 in Chapter 3.) Although the two sets of operators are not interchangeable due to precedence, once they're parsed, the operators themselves behave identically; precedence merely governs the extent of their arguments. Table 1.1 lists logical operators.
Since the logical operators "short-circuit" the way they do, they're often used in Perl to conditionally execute code. The following line (line 3 from our Average 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, this line means "Open
grades or bust!" 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 Chapter
28.) 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.) Assuming left and right arguments of
$a
and $b
, we have:
The last pair of operators
(<=>
and cmp
) are
entirely redundant. However, they're incredibly useful in
sort
subroutines (see Chapter 29).[19]
The file test operators allow you to test whether certain file attributes are set before you go and blindly muck about with the files. The most basic file attribute is, of course, whether the file exists. For example, it would be very nice to know whether your mail aliases file already exists before you go and open it as a new file, wiping out everything that was in there before. Here are a few of the file test operators:
You might use them like this:
-e "/usr/bin/perl" or warn "Perl is improperly installed\n"; -f "/vmlinuz" and print "I see you are a friend of Linus\n";
Note that a regular file is not the same thing as a text file. Binary files like /vmlinuz 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, which is to say they take only one operand (a scalar that evaluates to a filename 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 in the Section 3.10 in Chapter 3.
[16] Thought we'd forgotten it, didn't you?
[17] This is unlike, say, Pascal, in which assignment is a statement and returns no value. We said earlier that assignment is like a procedure, but remember that in Perl, even procedures return values.
[18] The optimizer will notice this and optimize the post-increment into a pre-increment, because that's a bit faster to execute. (You didn't need to know that, but we hoped it would cheer you up.)
[19] Some folks feel that such redundancy is evil because it keeps a language from being minimalistic, or orthogonal. But Perl isn't an orthogonal language; it's a diagonal language. By this we mean that Perl doesn't force you to always go at right angles. Sometimes you just want to follow the hypotenuse of the triangle to get where you're going. TMTOWTDI is about shortcuts. Shortcuts are about efficiency.
Get Programming Perl, 3rd Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.