Perl Programming/Operators
Introduction
[edit | edit source]Perl's set of operators borrows extensively from the C programming language. Perl expands on this by infusing new operators for string functions (.=, x, eq, ne, etc.). C by contrast delegates its subset of Perl functionality to a library strings.h, and ctype.h, and includes no such functionality by default compilation. Perl also includes a highly flexible Regex engine inspired by Sed with improvements to standard POSIX regexes, most notably the support of Unicode.
The operators
[edit | edit source]Arithmetic
[edit | edit source]Most arithmetic operators are binary operators; this means they take two arguments. Unary operators only take one argument. Arithmetic operators are very simple and often transparent.
Binary
[edit | edit source]All the basic arithmetic operators, addition (+), subtraction (-), multiplication (*), and division (/), and the modulus operator % exist. Modulus returns the remainder of a division (/) operation.
# 3 goes into 4, 1 time with 1 left over.
print 4%3; # prints 1
# 2 goes into 4, 2 times with 0 left over.
print 4%2; # prints 0
# 3 goes into -4, -2 times with 2 left over.
print -4%3; # prints 2
The exponentiation operator is **. It allows you to raise one value to the power of another. If you raise to a fraction you will get the root of the number. In this example the second result when raised to the power of 2 should return 2 ((2**(1/2))**2 = 2).
# Four squared:
print 4**2; # prints 16
# Square root of 2
print 2**(1/2); # prints 1.4142135623731
The function sqrt is provided for finding a square root. Other fractional powers (i.e., (1/5), (2/13), (7/5), and similar) are suitably found using the ** operator.
Unary
[edit | edit source]The auto-decrement (--), and auto-increment (++) operators are unary operators. They alter the scalar variable they operate on by one logical unit. On numbers, they add or subtract one. On letters and strings, only the auto-increment shift one up in the alphabet, with the added ability to roll-over. Operators that come in post- and pre- varieties can be used two ways. The first way returns the value of the variable before it was altered, and the second way returns the value of the variable after it was altered.
my $foo = 1;
# post decrement (printed and then decremented to 0)
print $foo--; # prints 1
print $foo; # prints 0
my $foo = 1;
# pre-decrement (decremented to 0 then printed)
print --$foo; # prints 0
print $foo; # prints 0
my $foo = 'd';
# pre-increment (incremented to e then printed)
print ++$foo; # prints e
print $foo; # prints e
my $foo = 'Z';
# post-increment (printed the incremented to AA)
print $foo++; # prints Z
print $foo; # prints AA
Assignment
[edit | edit source]The basic assignment operator is = that sets the value on the left side to be equal to the value on the right side. It also returns the value. Thus you can do things like $a = 5 + ($b = 6), which will set $b to a value of 6 and $a to a value of 11 (5 + 6). Why you would want to do this is another question.
The assignment update operators from C, +=, -=, etc. work in perl. Perl expands on this basic idea to encompass most of the binary operators in perl.
operator | name |
---|---|
+= | add assign, plus-equals |
-= | subtract assign, minus-equals |
*= | multiply assign |
/= | divide assign |
%= | modulo assign |
**= | exponent assign |
.= | concatenate assign |
x= | repeat assign |
&&= | logical AND assign |
||= | logical OR assign |
&= | bitwise AND assign |
|= | bitwise OR assign |
^= | bitwise XOR assign |
&.= | bitwise string AND assign |
|.= | bitwise string OR assign |
^.= | bitwise string XOR assign |
<<= | left shift assign |
>>= | right shift assign |
//= | defined OR assign |
my $foo = 'Hello';
$foo .= ', world';
print $foo; # prints 'Hello, world';
my $bar = '+';
$bar x= 6;
print $bar; # prints '++++++';
Comparison
[edit | edit source]Perl uses different operators to compare numbers and strings. This is done, because in most cases, Perl will happily stringify numbers and numify strings. In most cases this helps, and is consistent with Perl's DWIM Do-What-I-Mean theme. Unfortunately, one place this often does not help, is comparison.
name | numeric | string |
---|---|---|
equal | == | eq |
not equal | != | ne |
less than | < | lt |
greater than | > | gt |
less or equal | <= | le |
greater or equal | >= | ge |
compare | <=> | cmp |
Logical
[edit | edit source]Perl has two sets of logical operators, just like the comparison operators, however not for the same reason.
The first set (sometimes referred to as the C-style logical operators, because they are borrowed from C) is &&, ||, and !. They mean logical AND, OR, and NOT respectively. The second set is and, or, and not.
The only difference between these two sets is the precedence they take (See Precedence). The symbolic operators take a much higher precedence than the textual.
Conditionals
[edit | edit source]Most of the time, you will be using logical operators in conditionals.
# Only prints "I like cookies\n", if both $a is 5 and $b is 2
if ($a == 5 && $b == 2) {
print "I like cookies\n";
}
In this case, you could safely substitute and for && and the conditional would still work as expected. However, this is not always the case.
#True, if $a is 5, and either $b, $c, or both are 2
if ($a == 5 and $b == 2 || $c == 2) {
print "I like cookies\n";
}
#Using brackets, the order is made more clear.
#This conditional acts in the same way as the last.
if ($a == 5 and ($b == 2 || $c == 3)) {
print "I like cookies\n";
}
This, however, is completely different.
if ($a == 5 && $b == 2 or $c == 3) {
print "I like cookies\n";
}
#Equivalent and easier to understand with brackets
if (($a == 5 && $b == 2) or $c == 3) {
print "I like cookies\n";
}
Most people prefer to use C-style logical operators and use brackets to enforce clarity rather than using a combination of textual and C-style operators (when possible), which can be very confusing at times.
Partial evaluation
[edit | edit source]Partial evaluation (or "short circuiting") is the property of logical operators that the second expression is only evaluated, if it needs to be.
($a, $b) = (5, 2);
#$b < 3 is not evaluated at all, because when the interpreter
#finds that $a == 4 is false, there is no need to evaluate $b < 3
#because the conditional is automatically false
if ($a == 4 && $b < 3) {
print "I like cookies\n";
}
This also works with logical OR statements. If the first expression evaluates as true, the second is never evaluated, because the conditional is automatically true.
This becomes useful in a case like this:
sub foo {
#returns a true or false value
}
foo() or print "foo() failed\n";
Here, if the foo() subroutine returns false, "foo() failed\n" is printed. However, if it returns true, "foo() failed\n" is not printed, because the second expression (print "foo() failed\n") does not need to be evaluated.
Bitwise
[edit | edit source]These operators perform the same operation as the logical operators, but instead of being performed on the true/false value of the entire expressions, it is done on the individual respective bits of their values.
- & (bitwise AND)
- | (bitwise OR)
- ^ (bitwise XOR)
- ~ (bitwise NOT)
The left and right shift operators move the bits of the left operand (e.g. $a in the case of $a << $b) left or right a number of times equal to the right operand ($b). Each move to the right or left effectively halves or doubles the number, except where bits are shifted off the left or right sides. For example, $number << 3 returns $number multiplied by 8 (2**3).
- << (left shift)
- >> (right shift)
String
[edit | edit source]The string concatenation operator is ., not + that some other languages use.
print 'Hello' . ' world'; # prints "Hello world" without a newline at the end
There is a repeat operator for strings (x) that repeats a string a given number of times.
my $str = "hi";
my $repeated_str = $str x 5;
print "$repeated_str\n"; # prints "hihihihihi" with a newline at the end
Comparing strings
[edit | edit source]To compare strings, use eq and ne instead of == or != respectively. You can also look for a substring with substr(), or pattern-match with regular expressions.
File Test
[edit | edit source]Other
[edit | edit source]The range operator (..) returns a list of items in the range between two items; the items can be characters or numbers. The type of character is determined by the first operand; the code:
print ('A'..'Z'); print ('a'..'z'); print ('A'..'z'); print (1..'a'); print (1..20); print ('&'..'!'); print (10..-10); print "$_\n" foreach (1..10);
Outputs (Newlines added for readability):
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
1234567891011121314151617181920 &
1 2 3 4 5 6 7 8 9 10
Note that the case is defined by the first operand, and that the 1..'a' and (10..-10) operations return empty list.
Precedence
[edit | edit source]Precedence is a concept that will be familiar to anyone who has studied algebra or coded in C/C++. Each operator has its place in a hierarchy of operators, and are executed in order. The precedence of perl operators is strict and should be overridden with parentheses, both when you are knowingly going against precedence and when you aren't sure of the order of precedence. For a complete listing of the order, check perlop.
The smart match operator
[edit | edit source]The smart match operator ~~ is new in perl 5.10. To use it, you'll need to explicitly say that you're writing code for perl 5.10 or newer. Its opposite operator ǃ~ matches smartly an inequality:
#!/usr/bin/perl
use strict;
use warnings;
use 5.10.0; # We will be using the smart match operator
my $foo = 'low';
my $scalar = 'hi';
my @array = qw(one two three);
my %hash = (
hi => 1,
ho => 2,
he => 3,
);
if ($scalar ~~ @array) { print "1\n"; } # Doesn't print; 'hi' isn't an element in @array
if ($scalar ~~ %hash) { print "2\n"; } # Does print; 'hi' is a key in %hash
if (@array ~~ %hash) { print "3\n"; } # Doesn't print; none of the elements of @array match a key in %hash
if ($foo !~ %hash) { … }
The smart match operator is versatile and fast (often faster than the equivalent comparison without ǃ~ or ~~). See smart matching in detail for the comparisons it can do. ~~ is also used in the given/when switch statement new in 5.10, which will be covered elsewhere.
Dereferencing
[edit | edit source]The doubledollar
[edit | edit source]A variable, previously referenced with the reference operator can be dereferenced by using a doubledollar symbol prefix:
$number = 12;
$refnum = \$number; # backslash is the reference operator
$$refnum = 13; # $$ is used as a dereference to the original variable
$($refnum) = 11; # This is an alternative syntax using brackets
print $number; # the original variable has changed
The arrow operator
[edit | edit source]If the left hand operand of the arrow operator is an array or hash reference, or a subroutine that produces one, the arrow operator produces a look up of the element or hash:
$result = $hashreference -> {$key}; # look up a hash key from a reference variable
@arrayslice = $arrayreference -> [3 .. 5]; # obtain a slice from an array reference