Perl

Let’s start programming in Perl.

Overview

Perl is now a family of languages. All languages in the family except Perl 5 and Raku are obsolete.

The Perl language are very popular, “particularly well-suited for tasks involving quick prototyping, system utilities, software tools, system management tasks, database access, graphical programming, networking, and world wide web programming... [though] probably not well-suited for real-time embedded systems, low-level operating systems development work like device drivers or context-switching code, complex multi-threaded shared-memory applications, or extremely large applications.” (from the Perl FAQ).

The Perl home page is at perl.org.

Perl was born in the 1980s but is still going! Here are a few of the versions and their release dates:

    1         1987-12-18
    2         1988-06-05
    3         1989-10-18
    4         1991-03-21
    5.000     1994-10-17
    5.005     1998-07-22
    5.6       2000-03-28
    5.8       2002-07-18
    5.10      2007-12-18
    5.12      2010-04-12
    5.14      2011-05-14
    . 
    .
    .
    5.32      2020-06-20
    5.34      2021-05-20

See the complete Perl history at perlhist.

Hello, World

hello.pl
# The classic hello world script.

print "Hello, World\n";

To compile and run this, just enter

    perl hello.pl

On a Unix system, you can simply rename the file hello (instead of hello.pl), add a shebang comment with the pathname of your perl interpreter, and give the file executable permission.

More Simple Examples

Here is a cute little one with for loops:

triple.pl
# A script to print some Pythagorean triples.

for $c (1..100) {
    for $b (1..$c) {
        for $a (1..$b) {
            if ($a * $a + $b * $b == $c * $c) {
                printf "%4i%4i%4i\n", $a, $b, $c;
            }
        }
    }
}

and a Fibonacci numnber script that illustrates command line arguments

fib.pl
# A script to write the Fibonacci numbers up to and including the
# first commandline argument.

my $n = shift;

my ($a, $b) = (0, 1);
while ($b < $n) {
    print "$b ";
    ($a, $b) = ($b, $a + $b);
}

and one that illustrates subroutines

stats.pl
# A simple script that displays the mean and median
# of an array of values, passed in on the command line.

use strict;
use warnings;

sub median {
    my @a = sort {$a <=> $b} @_;
    my $length = scalar @a;
    return undef unless $length;
    ($length % 2)
        ? $a[$length/2]
        : ($a[$length/2] + $a[$length/2-1]) / 2.0;
}

sub sum {
    my $total = 0;
    $total += $_ for (@_);
    $total;
}

sub mean {
    @_ ? sum(@_) / (scalar @_) : undef;
}

print "input array is: @ARGV\n";
print "sum is: " . sum(@ARGV) . "\n";
print "mean is: " . mean(@ARGV) . "\n";
print "median is: " . median(@ARGV) . "\n";
print "input array is: @ARGV (just making sure it did not change)\n";

Demonstration of Basic Features

This script attempts to walk you through some very basic elements of the language. For a better "tutorial" see perlintro.

introduction.pl
# Examples of declaring variables and subroutines, and using some
# of the built-in functions.

use strict;
use warnings;

# Perl scripts don't need special main functions, subroutines,
# or main classes; just start writing code.  End each statement
# with a semicolon.

print "Hello\n";

# Variables can be scalars, arrays or hashes.  You don't specify type
# names like int or string when you declare them.

my $x = 7;
my $y = $x * 2;
my @animals = ('cow', 'pig', 'horse', 'beetle', 'whale');
my %numbers = ('odin' => 1, 'dva' => 2, 'tri' => 3);

# Perl has assignment statements.

$x = 35;
$x = $x * 4;
$x = "Another string";
$x = 75.2E4;
$x = 99;

# There are some built-in variables with really funny names

$, = "|";

# Strings can be in single or double quotes, but only double
# quotes interpolate escape characters and variables.

print 'The answer is $x \n';
print "The answer is $x \n";
print "$x cubed is " . $x ** 3 . "\n";

# Index arrays with [], get the index of the last element with #, and
# and get the length of the array by using it in a "scalar context".

my @stuff = (4.5, "cat", 2, 'dog', 'bear', 100);
print $stuff[0], $stuff[1], $#stuff, "\n";
$x = @stuff;
print "$x\n";
print "Six\n" if @stuff == 6;
print "@stuff\n";
print "@stuff[1, 4, 5]\n";
print "@stuff[2..4]\n";

# Using hashes

print $numbers{'dva'}, "\n";
$numbers{'chityri'} = 4;
print %numbers, "\n";
print "%numbers\n";

# Tired of writing the "\n" all the time?  How about writing a subroutine?
# Within the subroutine's body, all the parameters have been collected
# into the @_ variable.

sub println {
    local $, = '|';
    print @_;
    print "\n";
}

# Some built-in array functions

my @numbers = (2,3,4,5);

push @numbers, 6, 7, 8;
println @numbers;
pop @numbers;
println @numbers;
unshift @numbers, 0, 1;
println @numbers;
shift @numbers;
shift @numbers;
$x = shift @numbers;
println "$x was shifted off of @numbers";

Types

There are few kinds of types:

You can only make variables of the first three types.

Names for scalars start with $, arrays with @, hashes with %, subroutines with &, and typeglobs with *. The others just start with letters so don’t get them confused with keywords.

You cannot make arrays of arrays, or arrays of hashes, or arrays of arrays and hashes, or hashes of arrays, or hashes of hashes, or hashes of arrays and hashes. But you can put references in arrays and hashes because references are scalars, so you can get whatever data structure you really want.

Declarations

A declaration can go anywhere a statement can go. Declarations can be scoped with my, our, or local.

ourmylocal.pl
use strict;
use warnings;

our $x = 1;
our $y = 101;
our $z = 201;

sub g {
    print "Entering g\n";
    print "In g, x = $x and y = $y and z = $z\n";
    print "Leaving g\n";
}

sub f {
    print "Entering f\n";
    my $x = 2;
    local $y = 102;
    $z = 202;
    print "In f, assigned my x = $x and local y = $y and z = $z\n";
    g();
    print "Leaving f\n";
}

print "Initially globals x = $x and y = $y and z = $z\n";
f();
print "Finally globals x = $x and y = $y and z = $z\n";

Statements

A Perl statement is either an expression (possibly with a modifier) or an if, unless, while, until, or for statement.

    SIMPLE_STATEMENT → EXPR MODIFIER?

    MODIFIER →  if EXPR
             |  unless EXPR
             |  while EXPR
             |  until EXPR
             |  (for|foreach) LIST

    COMPOUND_STATEMENT →
          if '(' EXPR ')' BLOCK (elsif '(' EXPR ')' BLOCK)* (else BLOCK)?
        | unless '(' EXPR ')' BLOCK (elsif '(' EXPR ')' BLOCK)* (else BLOCK)?
        | LABEL? while '(' EXPR ')' BLOCK (continue BLOCK)?
        | LABEL? until '(' EXPR ')' BLOCK (continue BLOCK)?
        | LABEL? (for|foreach) '(' EXPR ';' EXPR ';' EXPR ')' BLOCK
        | LABEL? (for|foreach) VAR? '(' LIST ')' (continue BLOCK)?

Operators

Here are the Perl operators, presented from highest to lowest precedence.

Operator(s)AssociativityComments
Terms No Variables, quote and quote-like operators, parenthesized expressions, subroutine or operator call with parenthesized args, [] constructor, {} constructor, do{}, eval{}, sub{}
->
Left Infix dereference
++  --
No Increment, decrement
**
Right Exponentiation
!  ~  \  +  -
Right Unary prefix operators: logical not, bitwise complement, reference creator, unary plus, unary negation
=~  !~
Left Binding (binds a string to a pattern match, substitution, or transliteration).
*  /  %  x
Left multiply, divide, modulo, string repetition
+  -  .
Left numeric add, numeric subtract, string concatenation
<<  >>
Left bitwise shifts
Named unary operators Right There are around 75 of these, including the 27 filetest operators. Examples: chdir, exists, length, scalar, sin, sqrt. Make your own by using the ($) prototype.
<  <=  >  >=
lt  gt  le  ge
No less-than, less-than-or-equal, greater-than, greater-than-or-equal
==  !=  <=>
eq, ne, cmp
No equal-to, not-equal-to, compare
&
Left bitwise-and
|  ^
Left bitwise-or, bitwise-xor
&&
Left logical-short-circuit-and
||
Left logical-short-circuit-or
.. ...
No Range operators
?: Right conditional
=  **=  +=  -=  .=
*=  /=  %=  x=
&=  |=  ^=
<<=  >>=  &&=  ||=
Right assignment
,  =>
Left comma
List operators Right Basically, these are the functions that aren’t explicitly named unary operators.
not
Right Logical negation
and
Left logical-short-circuit-and
or  xor
Left logical-short-circuit-or, logical xor

Built-in Functions

Perl has a couple hundred functions (you can call them operators, too) that aren’t part of any package. They are:

Scalars chomp, chop, chr, crypt, hex, index, lc, lcfirst, length, oct, ord, pack, q/STRING/, qq/STRING/, reverse, rindex, sprintf, substr, tr///, uc, ucfirst, y///
Regexs/pattern matching m//, pos, quotemeta, s///, split, study, qr//
Numerics abs, atan2, cos, exp, hex, int, log, oct, rand, sin, sqrt, srand
For real @ARRAYs pop, push, shift, splice, unshift
For list data grep, join, map, qw/STRING/, reverse, sort, unpack
%HASHes delete, each, exists, keys, values
Input and output binmode, close, closedir, dbmclose, dbmopen, die, eof, fileno, flock, format, getc, print, printf, read, readdir, rewinddir, seek, seekdir, select, syscall, sysread, sysseek, syswrite, tell, telldir, truncate, warn, write
Fixed length data pack, read, syscall, sysread, syswrite, unpack, vec
Filehandles, files, directories -X, chdir, chmod, chown, chroot, fcntl, glob, ioctl, link, lstat, mkdir, open, opendir, readlink, rename, rmdir, stat, symlink, sysopen, umask, unlink, utime
Control flow caller, continue, die, do, dump, eval, exit, goto, last, next, redo, return, sub, wantarray
Scoping caller, import, local, my, our, package, use
Miscellaneous defined, dump, eval, formline, local, my, our, reset, scalar, undef, wantarray
Processeses and process groups alarm, exec, fork, getpgrp, getppid, getpriority, kill, pipe, qx/STRING/, setpgrp, setpriority, sleep, system, times, wait, waitpid
Modules do, import, no, package, require, use
Classes and OOP bless, dbmclose, dbmopen, package, ref, tie, tied, untie, use
Sockets accept, bind, connect, getpeername, getsockname, getsockopt, listen, recv, send, setsockopt, shutdown, socket, socketpair
System V IPC msgctl, msgget, msgrcv, msgsnd, semctl, semget, semop, shmctl, shmget, shmread, shmwrite
User and group endgrent, endhostent, endnetent, endpwent, getgrent, getgrgid, getgrnam, getlogin, getpwent, getpwnam, getpwuid, setgrent, setpwent
Networking endprotoent, endservent, gethostbyaddr, gethostbyname, gethostent, getnetbyaddr, getnetbyname, getnetent, getprotobyname, getprotobynumber, getprotoent, getservbyname, getservbyport, getservent, sethostent, setnetent, setprotoent, setservent
Time gmtime, localtime, time, times

Note: If you’re the type that doesn’t use a lot of parentheses, then you need to remember which of these are list operators and which of these are true unary operators! Good luck!

Predefined Variables

See http://perldoc.perl.org/perlvar.html for the complete list.

Packages

Perl has pacakges for namespace control, and some nice syntax to make object oriented programming look pleasant.

packagedemo.pl
$x = 1;

package A;
$x = 2;

package B;
$x = 3;
print "$x\n";
print "$A::x\n";
print "$B::x\n";
print "$main::x\n";
print "$C::x\n";

package A;
$x = 7;
$B::y = 12;
sub f {print "The f in A\n";}
sub g {print "(", scalar(@_), " args) ", "@_\n";}

package B;
print "$y\n";
A::f();

package main;
print "$x\n";
A::g();
A::g(100);
A::g(1, 2, 3);
A->g();
A->g(100);
A->g(1, 2, 3);

package C;
A->g(100);

package A;
$y = {name=>"alice", age=>21};
print "$y\n";
print "%$y\n";
bless $y, "A";
print "$y\n";
print "%$y\n";
%x = %$y;
print "$x{name}\n";
g($y);
$y->g();
$y->g(400);
g();

package B;
print "%$A::y\n";
$A::y->g(100);
A->g(100);
g A(100);
g A;
A->g;

Modules

Modules allow for separate compilation. Keep the package names in sync with the file names and it all works out.

Trig.pm
# Trig.pm
#
# Just illustrates how to write a simple module.  Note this
# doesn't "export" anything, so all users have to qualify
# names.

use warnings;

package Trig;

$pi = atan2(1,1) * 4;

sub tan {
    sin($_[0]) / cos($_[0]);
}

sub circle_area {
    my $radius = shift;
    return $pi * $radius * $radius;
}

1;

To use...

frustum.pl
# This little script calculates frustum parameters given
# a vertical field of view and an aspect ratio.  The only
# reason I wrote this is to show how to use a user-defined
# module.

use Trig;

print "Did you know pi was about $Trig::pi?\n";

# Given: fovy, depth, aspect.
# Returns width, height.

sub frustum {
    my ($fovy, $depth, $aspect) = @_;
    my $height = (2 * $depth) * Trig::tan($fovy / 2);
    my $width = $aspect * $height;
    return ($width, $height);
}

$, = ",";
print frustum($Trig::pi/2, 10, 2);
print "\n";

More fun stuff with modules: BEGIN, END, AUTOLOAD. Privacy? Well you can’t stop other people from inserting names into your package’s namespace, but you can use "my" to "hide" variables and subroutine references.

Standard Modules

The "standard" ones are listed at http://perldoc.perl.org/perlmodlib.html but there are many others that have been contributed; see http://www.perl.com/CPAN/modules/00modlist.long.html.

Object Orientation

Perl’s OOP is based on the idea that

This example barely scratches the surface of what you can, and should, do:

animals.pl
# Very small, but classic, OOP demo.

use strict;
use warnings;

#
# Abstract base class.  Create animals of any subclass by calling
# new with the animal's name.  There is a speak method which delgates
# to the subclass-supplied sound subroutine.
#

package Animal;
sub new {
    my ($class, $name) = @_;            # first parameter is class name
    my $animal = {name => $name};       # representation is a hash
    bless $animal, $class;              # "tags" (blesses) the hash
    return $animal;                     # constructors return object refs
}

sub speak {
    my $self = shift;
    print $self->{name}, " says ", $self->sound(), "\n";
}

#
# Subclasses.
#

package Cow;
@Cow::ISA = qw(Animal);
sub sound { "moooo" }

package Horse;
@Horse::ISA = qw(Animal);
sub sound { "neigh" }

package Sheep;
@Sheep::ISA = qw(Animal);
sub sound { "baaaaa" }

#
# Illustration of use, showing the variety of styles one can
# use make an animal and tell it to speak.
#

package main;
my $s = Horse->new("CJ");               # The usual way to call "constructor"
$s->speak;                              # dispatches perfectly - see why?

my $c = new Cow "Bessie";               # Funny syntax to make C++ folks happy
$c->speak();

my $h = new Sheep("Little Lamb");       # In case you love parens
Animal::speak($h);                      # Works, but verbose and uncommon

Tutorials and references at perl.org: Beginner’s OO Tutorial, Tom’s OO Tutorial, Tom’s OO Tutorial for Class Data, and Reference page on Perl objects.

Miscellany

These notes are in no way meant to be complete. We barely got started! Here are a few things not covered in these notes: