Perl Part I · Module 12 · Modules and Packages
Writing Your First .pm File
Everything needed to write a module is now in place: Chapter 12.2 gave the package declaration, 12.3 gave the two ways a caller loads one, and 12.4 gave the search path that connects a module's name to a file on disk. This chapter puts them together into the file itself, which is shorter than people expect — a package line, strict and warnings, the subroutines, and a trailing true value. The two measurements are both failures, and both are worth meeting here rather than in a flow at four in the afternoon. One is the error from a forgotten final line, which is distinctive enough to recognise instantly once you have seen it. The other is subtler and genuinely surprising: Perl resolves a module name to a file path and loads that file without ever checking that the package declared inside it matches the name you asked for. A mismatched file loads with no complaint at all, and the error surfaces later, somewhere else, pointing at your script.
Intermediate11 min readPerlPart IModules
Part I · Module 12 · Chapter 12.5 · Writing Your First .pm File
1. The Six Steps
Creating a module file and calling it
Steps two, three, four and six are mechanical. Steps one and five are the ones that produce errors, and they are the subject of sections three and four.
2. The File
Here is the finished module — the same file Chapter 12.1 used to remove the duplication between two reports.
package VLSI::Log;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT_OK = qw(parse_slack worst_slack);
sub parse_slack {
my ($line) = @_;
my ($pin, $slack) = $line =~ m{^(\S+)\s+(-?[\d.]+)\s*$};
return defined $pin ? { pin => $pin, slack => $slack + 0 } : undef;
}
sub worst_slack {
my (@rows) = @_;
my $worst;
for my $r (@rows) {
next unless defined $r;
$worst = $r if !defined $worst || $r->{slack} < $worst->{slack};
}
return $worst;
}
1;Six things to notice, in the order they appear.
The package line comes first, so everything declared below it belongs to VLSI::Log rather than to main. Chapter 12.2 covered the mechanism.
use strict and use warnings are not inherited from the caller. They are lexical — they apply to the file they appear in — so a module without them is unchecked no matter how careful the script loading it is. This is the single most common omission in a first module.
use Exporter 'import'; plus @EXPORT_OK is how the module offers names to callers. Chapter 12.6 is entirely about that choice, including why it is @EXPORT_OK and not @EXPORT.
The subroutines are ordinary subroutines. There is nothing module-specific about them, and everything from Module 10 applies unchanged.
parse_slack returns a hash reference with named fields, which is the shape argument from Chapter 12.1 — a caller that reads $row->{slack} keeps working when a third field is added.
The file ends with 1; — a bare true value. That is the next section.
3. The Trailing True Value
use strict;
use warnings;
use File::Temp qw(tempdir);
use File::Spec;
my $dir = tempdir(CLEANUP => 1);
mkdir File::Spec->catdir($dir, "VLSI");
# Two modules, identical except for the trailing true value.
my %body = (
"Good.pm" => "package VLSI::Good;\nsub tag { 'good' }\n1;\n",
"Bad.pm" => "package VLSI::Bad;\nsub tag { 'bad' }\n",
);
for my $f (sort keys %body) {
open my $fh, ">", File::Spec->catfile($dir, "VLSI", $f) or die $!;
print $fh $body{$f};
close $fh;
}
unshift @INC, $dir;
for my $mod (qw(VLSI::Good VLSI::Bad)) {
my $ok = eval "require $mod; 1";
if ($ok) {
printf "%-11s loaded\n", $mod;
}
else {
my ($first) = split /\n/, $@;
$first =~ s/ at .* line \d+\.?$//; # drop the eval location
printf "%-11s FAILED : %s\n", $mod, $first;
}
}VLSI::Good loaded
VLSI::Bad FAILED : VLSI/Bad.pm did not return a true valueTwo files differing by three characters, and one of them cannot be loaded:
VLSI/Bad.pm did not return a true value
The rule is that require evaluates the file and checks the value of its last expression. A module is required to end in something true, which by convention is 1;. The reason is historical — it let a module signal that its own initialisation had succeeded — and the requirement remains.
The error is at least specific: it names the file, and the phrase "did not return a true value" appears nowhere else. Once you have read it once you will recognise it, which is the main reason to provoke it deliberately here.
Two related traps follow from "the value of its last expression":
- A module ending in a subroutine definition is fine, because a
subdeclaration is not the last evaluated expression in the way you might fear — but a module ending in an assignment whose value happens to be0or""will fail. Ending in a literal1;avoids the question entirely. - A module ending in
return;inside no subroutine is a syntax error, not this error. If the message says something else, this is not your problem.
4. The Name Must Agree With the Path
use strict;
use warnings;
use File::Temp qw(tempdir);
use File::Spec;
my $dir = tempdir(CLEANUP => 1);
mkdir File::Spec->catdir($dir, "VLSI");
# The FILE is VLSI/Mismatch.pm but the PACKAGE inside says something else.
open my $fh, ">", File::Spec->catfile($dir, "VLSI", "Mismatch.pm") or die $!;
print $fh "package VLSI::SomethingElse;\nsub tag { 'surprise' }\n1;\n";
close $fh;
unshift @INC, $dir;
my $loaded = eval { require VLSI::Mismatch; 1 } ? "yes" : "no";
printf "require VLSI::Mismatch loaded the file : %s\n", $loaded;
# ...but the package it defined is NOT the one you asked for
my $direct = eval { VLSI::Mismatch::tag() } ;
printf "VLSI::Mismatch::tag() works : %s\n", (defined $direct ? "yes" : "no");
printf "VLSI::SomethingElse::tag() works : %s\n", VLSI::SomethingElse::tag();
print "\nPerl matches the FILE PATH; the package name inside is not checked\n";require VLSI::Mismatch loaded the file : yes
VLSI::Mismatch::tag() works : no
VLSI::SomethingElse::tag() works : surprise
Perl matches the FILE PATH; the package name inside is not checkedThis is the measurement to remember. require VLSI::Mismatch succeeded. The file was found, loaded, and returned true. And then VLSI::Mismatch::tag() does not exist, while VLSI::SomethingElse::tag() does.
Perl's two jobs here are completely separate. Chapter 12.4 showed the first: a module name is translated into a relative path and that file is loaded. Nothing in that process looks at the package line. The second job — deciding which namespace the subroutines land in — is done by the package statement inside the file, and it can say anything it likes.
This also explains two things that are otherwise puzzling. A file may legitimately declare several packages — Chapter 12.2's first example did — which is why Perl cannot simply insist on one matching name. And a module may deliberately declare a different package to make itself an alias for something else, which is a real if uncommon technique.
5. Calling It
With the file in place, the caller is three lines, and they are the three from Chapter 12.4:
use lib "$FindBin::Bin/../lib"; to put the project's library on the search path, anchored to the script rather than the working directory. Then use VLSI::Log qw(parse_slack worst_slack); to load the module and import the two names. Then call them as ordinary subroutines.
Chapter 12.1's one-source.pl is exactly that script, and its measurement is the point of the whole exercise: two reports that can no longer disagree, because there is one definition of the rule.
The layout convention worth adopting from the start is a directory per project with bin/ for scripts and lib/ for modules, with the module tree under lib/ mirroring the package names. VLSI::Log is lib/VLSI/Log.pm; VLSI::Report::Timing would be lib/VLSI/Report/Timing.pm. Everything in this module assumes that layout, and it is what use lib and PERL5LIB are designed for.
6. What To Remember
- A module file is four things: a
packageline,strictandwarnings, the subroutines, and a trailing true value. strictandwarningsare lexical and are not inherited from the caller. A module without them is unchecked however careful the script is.- The file must end in a true value, conventionally
1;. Measured: without it,VLSI/Bad.pm did not return a true value. - Perl matches the file path and never checks the package name inside. Measured: a mismatched file loaded successfully, and then the names you asked for did not exist while the ones you did not ask for did.
- That failure points at your script, not at the module — it arrives as
Undefined subroutine. Check thepackageline against the path. - A file may declare several packages, which is why Perl cannot insist on a single matching name.
- Return a named shape, as
parse_slackreturns a hash reference, so adding a field does not break callers. - Use
bin/andlib/, with the tree underlib/mirroring the package names.
Chapter 12.6 takes the one line in that file this chapter skipped over: what @EXPORT_OK does, why it is the right choice, and the measured difference between a module that waits to be asked and one that installs its names in your package whether you wanted them or not.
Where this fits
Part of the Perl curriculum.
