Modules
## Learning Objectives
- Understand packages and modules
- Use @INC and module loading
- Create and use modules
- Work with CPAN
- Use Exporter for exports
## Packages
### Package Declaration
```perl
package MyPackage;
# Package variables
our $VERSION = "1.0";
sub hello {
print "Hello from MyPackage!\n";
}
1; # Must return true
```
### Package Scope
```perl
package MyPackage;
my $private = "not visible";
our $public = "visible";
sub test {
print "$public\n"; # OK
print "$private\n"; # OK within same file
}
package main;
print "$MyPackage::public\n"; # Access with package::
# print "$MyPackage::private\n"; # Error - not visible
```
## Modules vs Packages
### Module Files
```perl
# MyModule.pm
package MyModule;
use strict;
use warnings;
sub greet {
return "Hello!";
}
1; # End with true value
```
### Using Modules
```perl
use strict;
use warnings;
# Direct package reference
use MyModule;
print MyModule::greet(), "\n";
# Or load at runtime
require MyModule;
```
## use vs require
### use
```perl
use strict; # Loads at compile time
use warnings;
use My::Module; # .pm file automatically found
# With import
use List::Util qw(sum max);
print sum(1, 2, 3); # 6
```
### require
```perl
require Some::Module; # Loads at runtime
# Or require a specific file
require "/path/to/MyModule.pm";
```
## @INC
### Understanding @INC
```perl
use strict;
use warnings;
# @INC contains directories to search for modules
print join "\n", @INC;
# Add directory to @INC
use lib "/my/custom/path";
BEGIN {
unshift @INC, "/my/path";
}
```
### Finding Module Paths
```perl
use strict;
use warnings;
# At runtime
perl -e 'print join "\n", @INC'
# In code
foreach my $path (@INC) {
print "$path\n";
}
```
### PERL5LIB
```bash
export PERL5LIB=/my/custom/lib:$PERL5LIB
perl script.pl
```
## Creating Modules
### Basic Module Template
```perl
package My::Module;
use strict;
use warnings;
our $VERSION = "1.00";
sub new {
my ($class, %args) = @_;
my $self = bless \%args, $class;
return $self;
}
sub greet {
my ($self) = @_;
return "Hello, $self->{name}!";
}
1;
```
### Module File Structure
```perl
# lib/My/Module.pm
package My::Module;
use strict;
use warnings;
our $VERSION = '1.00';
sub new {
my ($class, %args) = @_;
return bless \%args, $class;
}
1;
```
## Exporter
### Basic Exporter
```perl
package My::Utils;
use strict;
use warnings;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(celsius_to_fahrenheit add_numbers);
our @EXPORT_OK = qw(multiply_numbers);
sub celsius_to_fahrenheit {
my ($c) = @_;
return $c * 9/5 + 32;
}
sub add_numbers {
my ($a, $b) = @_;
return $a + $b;
}
sub multiply_numbers {
my ($a, $b) = @_;
return $a * $b;
}
1;
```
### Using Exporter
```perl
use strict;
use warnings;
# Gets @EXPORT by default
use My::Utils;
print celsius_to_fahrenheit(100); # 212
# Or import specific functions
use My::Utils qw(multiply_numbers);
print multiply_numbers(3, 4); # 12
# Import nothing
use My::Utils qw();
```
### Export Tags
```perl
package My::Math;
use strict;
use warnings;
use Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = (
basic => [qw(add subtract)],
advanced => [qw(multiply divide)],
);
our @EXPORT_OK = ( @{ $EXPORT_TAGS{basic} }, @{ $EXPORT_TAGS{advanced} } );
sub add { $_[0] + $_[1] }
sub subtract { $_[0] - $_[1] }
sub multiply { $_[0] * $_[1] }
sub divide { $_[0] / $_[1] }
1;
```
```perl
use My::Math qw(:basic);
print add(5, 3);
```
## CPAN
### Using CPAN
```bash
cpan Module::Name
cpanm Module::Name # Using cpanminus
```
### Installing Modules
```bash
# Using cpan
cpan install JSON
# Using cpanminus (recommended)
cpanm JSON
# Specific version
cpanm JSON@2.90
```
### Popular Modules
| Module | Purpose |
|--------|---------|
| JSON | JSON encoding/decoding |
| LWP::UserAgent | HTTP client |
| DBI | Database interface |
| Mojo::DOM | HTML parsing |
| DateTime | Date/time handling |
| Catalyst | Web framework |
| Dancer2 | Lightweight web framework |
| Test::More | Testing |
| Moose | OOP framework |
| Moo | Lightweight OOP |
### cpanfile
```perl
# cpanfile
requires 'JSON', '2.00';
requires 'List::Util', '1.45';
requires 'Path::Tiny';
on 'test' => sub {
requires 'Test::More', '0.98';
requires 'Test::Fatal', '0.013';
};
```
## Pragmas
### use strict
```perl
use strict;
# Requires variable declaration
my $var = "test";
# $undeclared = "error"; # Would error
# Requires package qualification
# $Other::var = "error"; # Error
```
### use warnings
```perl
use warnings;
# Warns about:
# - Using undef
# - Bareword filehandles
# - etc.
```
### Other Pragmas
```perl
use integer; # Integer arithmetic
use bytes; # Byte semantics
use utf8; # UTF-8 in source
use encoding 'utf8'; # UTF-8 in I/O
use autodie; # Automatic error handling
use feature 'say'; # Modern features
use 5.010; # Minimum version
```
## Object-Oriented Modules
### Basic Class
```perl
package Point;
use strict;
use warnings;
sub new {
my ($class, %args) = @_;
my $self = bless {
x => $args{x} // 0,
y => $args{y} // 0,
}, $class;
return $self;
}
sub x { my $s = shift; $s->{x} = shift if @_; $s->{x} }
sub y { my $s = shift; $s->{y} = shift if @_; $s->{y} }
sub distance {
my ($s, $other) = @_;
my $dx = $s->x - $other->x;
my $dy = $s->y - $other->y;
return sqrt($dx*$dx + $dy*$dy);
}
1;
```
### Using the Class
```perl
use strict;
use warnings;
use Point;
my $p1 = Point->new(x => 0, y => 0);
my $p2 = Point->new(x => 3, y => 4);
print $p1->distance($p2); # 5
```
## Module Directory Structure
### Standard Layout
```text
lib/
My/
Module.pm
t/
test.t
Makefile.PL # or Build.PL
MANIFEST
README
```
### Makefile.PL
```perl
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'My::Module',
VERSION_FROM => 'lib/My/Module.pm',
PREREQ_PM => {
'strict' => 0,
'warnings' => 0,
},
INSTALLDIRS => 'site',
);
```
## Summary
- Packages group code and provide namespaces
- Modules are .pm files containing packages
- `use` loads at compile time, `require` at runtime
- `@INC` contains search paths for modules
- `Exporter` handles function exports
- CPAN provides thousands of reusable modules
- Always use `strict` and `warnings`
- Module should return true at end
- Use `our` for package-scoped variables
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →