Perl Language
Introduction
Perl is a pragmatic, text-friendly language.
- Scripting language
- Strong text processing
- Dynamic typing
- Multi-paradigm (procedural, OO, functional style)
#!/usr/bin/env perl
use strict;
use warnings;
print "Hello World\n";
VS Code and Perl
Package Installation
sudo apt update
# Core build + Perl tooling
sudo apt install -y build-essential git perl perl-dbg cpanminus
# Common native libs used by CPAN modules
sudo apt install -y libssl-dev libreadline-dev zlib1g-dev libffi-dev libyaml-dev
# Postgres client/dev + DBI drivers
sudo apt install -y libpq-dev libdbi-perl libdbd-pg-perl
# Web framework (optional)
sudo apt install -y libmojolicious-perl
# If you build XS modules that need libperl/libaio
sudo apt install -y libperl-dev libaio-dev
Perl local::lib Environment Variables
Think of `local::lib` like Python `venv`: it gives you a user-scoped install location so your modules and scripts do not touch the system Perl. Unlike `venv`, it does not create a separate Perl executable; it adjusts environment variables so Perl loads modules from your local tree first. These are typical environment variables produced by `local::lib` to install CPAN modules into a user directory instead of system-wide.
PATH="/home/iwiseman/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/home/iwiseman/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/iwiseman/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/iwiseman/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/iwiseman/perl5"; export PERL_MM_OPT;
- PATH: prepends the local Perl `bin` so user-installed scripts are found first.
- PERL5LIB: adds the local Perl library path so `use` and `require` can find modules.
- PERL_LOCAL_LIB_ROOT: tracks the base directory used by `local::lib` (can be stacked).
- PERL_MB_OPT: tells `Module::Build` to install into the local base.
- PERL_MM_OPT: tells `ExtUtils::MakeMaker` to install into the local base.
Running
If you have Perl installed, you can run a script directly.
perl script.pl
Debugging
Install the "Perl" extension for VS Code by Gerald Richter to get a Perl language server (syntax checking, symbol navigation, etc.) and debugger integration. VS Code can then debug with the Perl debugger using a launch configuration like this:
{
"version": "0.2.0",
"configurations": [
{
"type": "perl",
"request": "launch",
"name": "Perl Debug App",
"program": "${workspaceFolder}/script/app.pl",
"args": ["daemon", "-l", "http://0.0.0.0:5001", "-m", "production"],
"env": {
"MOJO_REACTOR": "POLL"
},
"cwd": "${workspaceFolder}",
"stopOnEntry": false,
"reloadModules": true
}
]
}
Package Management
Which package manager?
Perl modules can come from your OS or from CPAN.
- OS packages (e.g. `apt install libmojolicious-perl`): stable, integrated with the distro; best for tools your whole system depends on.
- CPAN + `cpan` client: ships with Perl; interactive shell for installing modules from CPAN.
- CPAN + `cpanm` (cpanminus): lightweight command-line client; common choice for application projects, especially with `local::lib` or Carton.
For project code, prefer `cpanm` + a `cpanfile` over installing into the system Perl.
Listing what you have
Some ways to see what is installed or where it came from:
# Show where a module is loaded from
perl -MData::Dumper -e 'print $INC{"Data/Dumper.pm"}, "\n";'
# Per-module location via perldoc
perldoc -l Mojolicious
# Distro-level Perl modules (Debian/Ubuntu)
apt list --installed '*perl*'
Installing modules
Using `cpanm` (recommended for app code):
# Install a module into your local::lib tree
cpanm Mojolicious
# Install all dependencies for a project described in cpanfile
cpanm --installdeps .
Using the core `cpan` client:
cpan Mojolicious
Using the OS package manager (Debian/Ubuntu example):
sudo apt install libmojolicious-perl
Removing modules
Perl does not have a universal uninstall command for all clients, so strategy depends on how you installed:
- OS packages: use the package manager (e.g. `sudo apt remove libmojolicious-perl`).
- `local::lib` tree: you can safely remove or recreate the whole `/home/iwiseman/perl5` tree if it only holds project-local modules.
- `cpanm`: recent versions support uninstall for some cases, but many people simply clean and reinstall into a fresh `local::lib`.
Searching for modules
Most searching is done via websites, but you can also search from the shell.
# Search on MetaCPAN (browser)
https://metacpan.org
# Search in the legacy CPAN shell
cpan
cpan[1]> m /Mojo/
Avoiding and resolving conflicts
- Avoid mixing system packages and CPAN installs for the same module (choose one source per module).
- Use `local::lib` (and optionally Carton + `cpanfile`) so each project has its own module versions.
- If things get messy in your local tree, it is often easier to remove `/home/iwiseman/perl5` and reinstall the modules you actually need.
Useful sites
- MetaCPAN: https://metacpan.org – modern search and documentation for CPAN modules.
- CPAN: https://www.cpan.org – canonical archive of Perl distributions.
- BackPAN: https://backpan.perl.org – historical archive of old distribution versions (usually not needed day-to-day).
Types
Perl has scalars, arrays, and hashes. Scalars can hold strings, numbers, and references.
- Scalars: numbers, strings, references
- Arrays: ordered lists
- Hashes: key/value maps
Numbers
Perl uses numeric context for arithmetic.
my $one = 1; # integer
my $pi = 3.14159; # float
my $big = 1_000_000; # underscore for readability
Strings
Double quotes interpolate variables and escapes; single quotes do not.
my $name = "Perl";
my $greet = "Hello, $name\n";
my $raw = 'Hello, $name\n';
print $greet;
print $raw;
Arrays
Arrays are ordered lists.
my @numbers = (1, 2, 3, 4, 5);
print $numbers[2]; # 3
Hashes
Hashes map keys to values.
my %ages = (
Alice => 30,
Bob => 25,
);
print $ages{Alice};
Collections
Filtering and Mapping
Perl uses grep for filtering and map for transforms.
my @ints = (1, 2, 3, 4, 5);
my @small = grep { $_ < 4 } @ints;
my @squares = map { $_ * $_ } @ints;
Combining
my @ints = (1, 2, 3, 4, 5);
my @small_squares = map { $_ * $_ }
grep { $_ < 4 } @ints;
Flow Control
If
if ($answer eq $correct_answer) {
print "You were correct\n";
} else {
print "Try again\n";
}
Given/When
Perl supports a switch-like feature via given/when (use with feature). Note: it is experimental in some versions.
use feature 'switch';
my $number = 3;
given ($number) {
when (0) { print "Invalid number\n"; }
when ([1,2]) { print "Number too low\n"; }
when (3) { print "Number correct\n"; }
when (4) { print "Number too high, but acceptable\n"; }
default { print "Number too high\n"; }
}
For and Foreach
for (my $i = 0; $i < 5; $i++) {
print $i;
}
foreach my $n (@numbers) {
print $n;
}
Community Notes
Popular Today
- Perl 5 – the mainline Perl most people mean when they say “Perl”; actively maintained, widely deployed in sysadmin, web, data-processing and scripting.
- Mojolicious – modern, non-blocking web framework (routers, templates, testing helpers, WebSockets, etc.); good default choice for new web apps.
- DBI / DBD::* – standard way to talk to databases (e.g. `DBD::Pg` for Postgres); forms the base for higher-level ORMs.
- Carton / cpanminus – common tools to manage project-specific dependencies from CPAN (`cpanm`) and lockfiles (`Carton`) without touching system Perl.
Less Popular / Legacy
- Perl 6 / Raku – Perl 6 was renamed to Raku and is now its own language and community; interesting, but not a path for “upgrading” Perl 5 code.
- CGI.pm – classic module for raw CGI-style web programming; still works, but most new code uses PSGI/Plack or frameworks like Mojolicious instead.
- mod_perl-only stacks – historically popular for embedding Perl in Apache; many new projects prefer FastCGI, PSGI/Plack, or Mojolicious daemons behind nginx/Apache.
Starting a Real Project: dvdrental_api_pl
This section sketches how to go from an empty directory to the current dvdrental_api_pl REST API setup. Details of routes and database schema can live on a separate page.
1. Create the project skeleton
mkdir -p dvdrental_api_pl/{lib,script}
cd dvdrental_api_pl
# Optional: initialise git
git init
Recommended layout for this project:
- script/app.pl – Mojolicious application entry point (matches the VS Code debug config).
- lib/DVD/... – your application modules (e.g. DVD::API, DVD::Model::Rental).
- Documentation/ – wiki pages like this one.
2. Set up local Perl environment
Use local::lib (or similar) so project modules do not touch the system Perl.
perl -Mlocal::lib >> ~/.bashrc
source ~/.bashrc
After that, verify the environment variables look like the ones described in the local::lib section above (PATH, PERL5LIB, etc.).
3. Install project dependencies
Use cpanm with a cpanfile (recommended). A minimal cpanfile for a Mojolicious + Postgres REST API might look like:
requires 'Mojolicious';
requires 'DBI';
requires 'DBD::Pg';
requires 'JSON::MaybeXS';
Then install:
cpanm --installdeps .
You can also mix in OS packages for heavy C libraries (e.g. libpq-dev) as shown in the Package Installation section.
4. Create a minimal Mojolicious REST stub
Create script/app.pl to expose at least one test route.
#!/usr/bin/env perl
use strict;
use warnings;
use Mojolicious::Lite;
get '/health' => sub ($c) {
$c->render(json => { status => 'ok' });
};
app->start;
Run it manually to confirm it works:
perl script/app.pl daemon -l http://0.0.0.0:5001
curl http://localhost:5001/health
Later, this stub can be replaced by a full application class living under lib/DVD/..., but this is enough to validate the toolchain.
5. Hook up VS Code debugging
Use the launch configuration shown earlier ("Perl Debug App") so VS Code runs script/app.pl in daemon mode:
- Program: ${workspaceFolder}/script/app.pl
- Args: ["daemon", "-l", "http://0.0.0.0:5001", "-m", "production"]
- Env: MOJO_REACTOR=POLL
Set a breakpoint inside the /health route and verify that requests from curl or a browser hit the breakpoint.
6. Connect to the dvdrental database
Once the basic REST skeleton works, add a module under lib/DVD/ that uses DBI/DBD::Pg to talk to the dvdrental Postgres database. A separate page can describe:
- Connection DSN and credentials.
- Simple SELECT examples.
- How routes map to SQL queries.
At this point you have:
- A local Perl environment (local::lib).
- Dependencies managed via cpanm/cpanfile.
- A Mojolicious app entry script with debug support in VS Code.
- A place (lib/DVD/...) to grow the dvdrental_api_pl REST API.