← Perl EnglishChapter 10 of 13

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 →