Perl Programming/Operators

From Wikibooks, open books for an open world
Jump to: navigation, search

← Flow control | Variables →


Introduction[edit]

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]

Arithmetic[edit]

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]

All the basic arithmetic operators are present: addition (+), subtraction (-), multiplication (*), and division (/).

The modulus operator is %. 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]

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]

The basic assignment operator is "=" which 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 NOT assign
<<= left shift assign
>>= right shift assign
my $foo = 'Hello';
$foo .= ', world'; 
print $foo; # prints 'Hello, world';              
 
my $bar = '+';
$bar x= 6;
print $bar; # prints '++++++';

Comparison[edit]

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]

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]

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]

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, then 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, then "foo() failed\n" is printed. However, if it returns true, then "foo() failed\n" is not printed, because the second expression (print "foo() failed\n") does not need to be evaluated.

Bitwise[edit]

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]

The string concatenation operator is ., not + which some other languages use.

print 'Hello' . ' world'; # prints "Hello world" without a newline at the end

There is a repeat operator for strings (x) which 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]

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]

See Perl Programming/Function Reference#-X

Other[edit]

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 don't return anything.

Precedence[edit]

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]

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:

#!/usr/bin/perl
use strict;
use warnings;
use 5.10.0; # We will be using the smart match operator
 
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

The smart match operator is versatile and fast (often faster than the equivalent comparison without ~~). 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]

The doubledollar[edit]

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]

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


Previous: Flow control Index Next: Variables