Modules & CPAN
๐ฆ Modules & CPAN
cpanm. This chapter covers the full picture: loading existing modules properly, writing and exporting your own, and CPAN itself โ one of the oldest, largest package ecosystems in programming, predating both npm and PyPI's modern form by well over a decade.
๐ฅ use vs. require
use List::Util qw(max min sum); # compile-time loading, imports specific symbols immediately say max(3, 7, 2); # 7 โ used directly, no package prefix needed require List::Util; # runtime loading, no automatic import say List::Util::max(3, 7, 2); # must fully qualify, or call ->import() manually
use is what you want for essentially all real code โ it loads the module and imports its exported symbols at compile time, before the rest of the script even runs. require loads at runtime instead, with no automatic import โ genuinely useful for the rarer case of conditionally loading a module based on logic that can't be known until the script is actually running.
โ๏ธ Writing Your Own Module
# Utils.pm package Utils; use strict; use warnings; sub shout { my ($text) = @_; return uc($text) . "!"; } 1; # required โ see this chapter's own warn-box
This reuses Chapter 3's package declaration directly โ a module is just a package, conventionally saved in a file matching its name (Utils.pm for package Utils;).
When use or require loads a file, Perl checks the file's last evaluated expression โ if it isn't true, loading fails with Utils.pm did not return a true value. The trailing 1; is a plain true value placed deliberately as the file's final statement, purely to satisfy this requirement. Forgetting it is a genuinely common first-module mistake โ the module's actual code can be entirely correct and still fail to load.
๐ค Exporting Symbols with Exporter
# Utils.pm package Utils; use Exporter 'import'; our @EXPORT_OK = qw(shout); # available, but NOT imported unless explicitly requested # calling script: use Utils qw(shout); say shout("hello"); # HELLO!
@EXPORT_OK lists symbols available for opt-in import โ the calling script must explicitly request them (use Utils qw(shout);). This is the recommended practice over the older @EXPORT, which exports everything listed unconditionally into every script that uses the module โ a real risk of silently colliding with the caller's own subroutine or variable names. Explicit opt-in keeps namespace pollution under the caller's control.
๐ The CPAN Ecosystem
CPAN (the Comprehensive Perl Archive Network) launched in 1995 โ genuinely one of the oldest centralized package repositories in programming, predating npm (2010) and PyPI's modern form by well over a decade. It's a significant part of why Perl became so practically useful early: an enormous, searchable library of community-published modules for nearly anything.
cpanm List::Util # cpanm (App::cpanminus) โ the modern, simple CPAN client cpanm --installdeps . # install everything listed in a project's cpanfile
A cpanfile declares a project's dependencies โ the direct Perl parallel to Course 1, Chapter 9's Python requirements.txt or Node's package.json.
โญ A Few Genuinely Useful CPAN Modules
| Module | What it's for |
|---|---|
Path::Tiny | The nicer file-handling wrapper previewed back in Course 1, Chapter 8 โ read/write a whole file in one call |
JSON::PP | JSON encoding/decoding โ actually part of Perl core since 5.14, no install needed |
Try::Tiny | A cleaner error-handling syntax, previewed ahead of Chapter 6 |
DateTime | Robust date/time handling, well beyond localtime's context-sensitive quirkiness from Chapter 2 |
๐ง A Worked Example โ A Small Module
# MathUtils.pm package MathUtils; use strict; use warnings; use Exporter 'import'; our @EXPORT_OK = qw(square cube); sub square { my ($n) = @_; return $n * $n; } sub cube { my ($n) = @_; return $n * $n * $n; } 1;
# script.pl use strict; use warnings; use feature 'say'; use MathUtils qw(square cube); say square(4); # 16 say cube(3); # 27
CPAN vs. pip/npm
The underlying model is the same across all three โ a central registry, a simple install command, community-published packages. The real difference is age and culture: CPAN's 1995 launch makes it genuinely older than npm or PyPI's current form by well over a decade, and it fostered a "there's already a well-tested module for this" culture in Perl development early โ much of the reason Perl earned a reputation as a practical, get-things-done language for real work, not just an academic one.
use vs require
Compile-time with automatic import, vs. runtime with none.
The trailing 1;
Every .pm file must end with a true value or loading fails.
@EXPORT_OK
Opt-in exporting โ safer than unconditional @EXPORT.
cpanm / cpanfile
The modern CPAN client, and a project's declared dependencies.
๐ป Coding Challenges
Challenge 1: Write and Use a Module
Write a module StringUtils.pm exporting a subroutine reverse_string via @EXPORT_OK. Write a separate script that uses it and prints the result of reversing "Perl".
Challenge 2: Diagnose the Missing 1;
Given a module file whose last line is a subroutine definition (with no trailing 1;), explain in one sentence what error occurs when a script tries to use it, and show the corrected final lines.
Challenge 3: use vs require
Write two versions of loading and calling List::Util's max function on the list (3, 9, 4) โ one using use with a qw() import list, one using require with a fully-qualified call โ and explain in one sentence the key difference between them.
๐ฏ What's Next
Next chapter: Error Handling โ die/eval, $@, and modern try/catch (Perl 5.34+).