SlideShare a Scribd company logo
In Perl parlance a ‘package’ is a way of
specifying a namespace, before we
examine the syntax of a package let’s
look at what a namespace is and the
benefits they can provide.
A rose by any other name
In essence a namespace is used to isolate
variables and functions into separate
“compartments” to help avoid name-
space pollution and collision.
Within a program all of the functions
and variables (including filehandles) are
from the ‘main’ package, to determine
which package the currently executing
code is in Perl provides the
‘__PACKAGE__’ constant:
print "Current package is: '";
print __PACKAGE__, "'n";
The ‘__PACKAGE__’ constant cannot be
placed within a double quoted string and
still be interpolated, by including it in
double quotes the literal value is
returned instead.
Creating a new package by using the
‘package’ function with the name of the
package you wish to create (Listing 1). A
package’s scope is terminated by the end
of the file, exiting the block the package
was declared in or declaring another
package afterward, as
shown in Listing 2.
Using a namespace
we can reuse variable
names in each package
using the ‘our’ key-
word to declare the
variables to exist with
a specific value within
a package (Listing 3).
This code will
compile and run but
give warnings.
Modules – Scratching Itches
Now you have been introduced to how
packages work you may be wishing you
had stopped reading at the copy and
paste coding section. Now that you have
seen the cost of code re-use the right way
we can introduce you to the benefits,
namely building modules.
A module is quite simply a package
placed in a separate file, where the file
name is the same as the package name
with a ‘.pm’ suffix so that Perl readily
recognizes the file as a “Perl Module”.
The code below is from a file called
Toaster.pm:
#this should be placed in
#a file called Toaster.pm
package Toaster;
our $VERSION = 1.00;
my $num_slots = 2;
my $toasting_time = 10;
sub roast_toast {
sleep $toasting_time;
print "Toast is donen";
return 0;
}
1;
The first line of a module IS ALWAYS the
package declaration, ensure the case of
the name matches the file-name. The
62 Dec 02 / Jan 03 www.linux-magazine.com
O
nce your code begins to grow
beyond a small script and into
large applications you will often
need to re-use small snippets, functions
or even collections of functions that you
have written in new applications. There
are two main ways you can set about
this re-use:
• copy and paste
• code abstraction
Unlike most choices in Perl there is only
one sensible way to do it.
Copy and pasting code may seem like
a quick and easy way to reproduce the
functionality you need but it has a
number of drawbacks that far out-weigh
any temporary time-savings.
The greatest of these issues is bug-
fixing, if you find a bug (and it WILL
happen) in a piece of code you have
manually copied and pasted into
multiple files then you will have to track
down each and every occurrence of the
code (Potentially even in files on
different machines so a simple find and
replace will not make the task any less
arduous for you) and make the change
numerous times.
You will also find that you frequently
make small incremental adjustments
to the code to make it fit better to the
task, so any enhancements will have
to be copied too. If just one instance
of the code is overlooked, then there are
different solutions to the same problem.
Fixing a bug in this manner will cost you
far more than any time you saved by
adopting this approach. Are you sure
you fixed that bug everywhere?
Now that we have covered the worst
way of implementing code re-use let’s
explain the principles behind the
preferred methods, packages and
modules. The commonly adopted
approach to code reuse is to write
functions and put them into a file in an
accessible location. The functions within
a file should be logically grouped
together by purpose. Functions whose
tasks have a similar theme are usually
placed in the same file.
To fit in with the festive season this month we are going to look at presents,
well packages to be exact but you can still think of them as little bundles of
coding joy.BY DEAN WILSON AND FRANK BOOTH
Thinking In Line Noise
Pre-wrapped Packages
Perl Tutorial: Part 7PROGRAMMING
#in the default package
print "Current package is '", __PACKAGE__, "'n";
package Huey;
print "In package ", __PACKAGE__, "'n";
package Louey;
print "In package ", __PACKAGE__, "'n";
package Dewey;
print "In package ", __PACKAGE__, "'n";
package main;
print "In package ", __PACKAGE__, "'n";
Listing 1: __PACKAGE__
module name should begin with an
uppercase letter, as a rule only pragmas
begin with a lowercase letter.
In the Toaster module we declare two
variables and a function. If you’re
wondering what the ‘1;‘ line at the end
of the code block is there for (in a real
module this would be at the end of the
file), it is required as all Perl modules
must evaluate to ‘true’ when they’re
compiled.
Although the value of the last evalu-
ated expression in the module would be
returned this is not guaranteed to evalu-
ate to ‘true’ as we can see by the
function ‘roast_toast’ returning ‘0’ so for
clarity and simplicity we explicitly return
‘1’ to ensure a correct compile and load.
Loading the Toaster
We now need to actually load the
module into our perl program when we
run the application so we can access the
functionality it provides.
Perl tracks the modules it has available
for use by storing a list of paths as a list
within which it looks for ‘.pm’ files. This
list is known as ‘@INC’ and is available
within perl itself for modification. Before
we move on to showing you how to add
your own directories let’s show two
possible ways to display the default
value of ‘@INC’.
The first way to do this is by allowing
Perl itself to do the work and show us
where it searches:
perl -V
You will then be shown a number of
details that describe many of the options
that this Perl interpreter was compiled
with. Underneath those details you will
find a section that resembles:
/usr/lib/perl5/5.6.0/i386-linux
/usr/lib/perl5/5.6.0
/usr/lib/perl5/site_perl/5.6.0/U
i386-linux
/usr/lib/perl5/site_perl/5.6.0
/usr/lib/perl5/site_perl
This information shows the default
locations that perl will search when you
have a ‘use’ statement in your code.
Two items of interest are that many
of the site directories have the version
number contained within them allowing
many versions of Perl to live happily on
the same machine while still allowing
easy identification of which version the
modules belong to.
The machine this was written on has
five versions for backwards compatibility
testing. The second item of interest is
that the current directory ‘.’ is included
by default.
The second way to show the searched
directories by using actual Perl code,
from the command line you can issue:
perl U
-we 'print map {
"$_n" } @INC;'
To generate a list of the default
directories that are printed to screen in
this format:
/usr/lib/perl5/5.6.0/i386-linux
/usr/lib/perl5/5.6.0
/usr/lib/perl5/site_perl/5.6.0/U
i386-linux
/usr/lib/perl5/site_perl/5.6.0
/usr/lib/perl5/site_perl
Recognize the directories it returns? This
is the same information that the Perl
interpreter itself told us about but the list
is available from within Perl itself.
Now we have provided a number
of different techniques
to retrieve and display
the current and default
values of ‘@INC’ we
will move on and step
though the list of ways
to coerce Perl into
looking in additional
locations for additional
modules including:
• ‘-I’ command line
switch
• Modifying @INC in
a BEGIN block
• ‘use lib’ pragma
The ‘-I’ method can
be a very long-winded
way of specifying
additional directories
and suffers from an
important drawback:
You have to remember
to add it with every
invocation of the
program.
# nvoke 'buildscript with
# build/directory added to @INC
perl -I build/directory U
buildscript.pl
In the above example of ‘-I’ we add the
‘build/directory/‘ to the ‘@INC’ list of
the ‘buildscript.pl’ script. Where ‘-I’
comes into its element is when used in
quick prototyping of very small projects,
however once your requirements grow to
the level where you need to specify
multiple additional include directories
you will begin to see the use of ‘-I’ as a
limiting factor to how far your project
can scale. We have not yet covered Perl’s
special blocks such as BEGIN or END in
this article but it is worth mentioning
this technique at this stage as a refer-
ence, although it is an oversimplification
at a basic level if you have a BEGIN
block in your code then its contents will
be executed before anything else in the
application is, including module loading.
# notice this should be executed
# first as it is before the
# BEGIN block
print "Normal Hellon";
BEGIN {
# this sections runs first
print "I'm run firstn";
}
63www.linux-magazine.com Dec 02 / Jan 03
PROGRAMMINGPerl Tutorial: Part 7
#in the default package
print "Current package is '", __PACKAGE__, "'n";
# Exiting the block the
# package was declared in
{
package Larry;
print "In package ", __PACKAGE__, "'n";
}
# Back to main package
print "In package ", __PACKAGE__, "'n";
# Closing a package by
# declaring a new package
package Moe;
print "In package ", __PACKAGE__, "'n";
# in this case the new
# package is main again.
package main;
print "In package ", __PACKAGE__, "'n";
# Package terminated by
# end of file.
package Curly;
print "In package ", __PACKAGE__, "'n";
Listing 2: Exiting the block
BEGIN block is inside
the Perl application it
is possible to use Perl
functions to alter the
values in ‘@INC’ and
so dynamically build-
ing a list of directories
is made simple with
very little additional
code or complexity
required.
The last of the more
common approaches
is using a pragma
known as ‘use lib’ to
specify the desired
additions. Using this
method is actually one of the simpler
ways of specifying new paths, it’s as sim-
ple as adding a call to the pragma at the
top of your program:
# !/usr/bin/perl -w
use strict;
use lib("/home/dwilson", U
"/home/wanttogo");
use CustomModule;
print "In main bodyn";
print "=" x 25, "n";
print join("n", @INC);
When this code snippet is run the two
additional directories are added to
‘@INC’ and then made available to the
rest of the program. If you ‘use’ modules
like this then you should always specify
the name of the module in a ‘use’ state-
ment AFTER the ‘use lib’ otherwise you
will get run-time errors, as shown in
Listing 4.
Although we did not define our own
BEGIN block in this code the module
loading is still done at this phase and the
error is caught before we go on any fur-
ther. The ease of use provided by ‘use
lib’ is significant and has a very low
learning curve that allows it to be used
in most of the cases where you would
want to add additional paths, once you
find yourself needing more flexibility
than this you will often have to resort
back to using BEGIN blocks with all the
power they provide, albeit at the cost of
greater complexity.
Invoking the mighty toaster
After wading through the coverage of
how to create your own packaged name-
space and then reading the details
surrounding the loading of modules you
are probably getting the itch to test your
new found knowledge with some
concrete code examples.
The examples throughout the rest
of this section assume that you have
the “Toaster” module in one of the
locations specified in ‘@INC’ so if
you have skipped past the previous
text you are going to be unable to
progress until you have gone back and
read it all.
You can test that you can access
“Toaster” correctly by running:
perl -MToaster -e 'print U
$Toaster::VERSION, "n";'
This should return ‘1’, if you see “Can’t
locate Toaster.pm in @INC” then the
module is not in the ‘@INC’ path and
you need to amend your configuration as
per the instructions given above ( in the
“Loading the Toaster” section ) before
64 Dec 02 / Jan 03 www.linux-magazine.com
As you would expect, it has a
corresponding END block. The code
contained within the block is ALWAYS
run just before the program finishes its
own execution.
print "running happily in ";
print __PACKAGE__, "n";
END {
print "exiting at ";
print scalar localtime();
print "n";'
}
Although we will delay the detailed look
at the full range of functionality these
two block types provide the more com-
mon uses of these blocks make sense
even without knowing all their intimate
details, END blocks are ideal places to
put clean up or summary code and
BEGIN blocks are a perfect place to alter
‘@INC’ as shown below:
# !/usr/bin/perl -w
use warnings;
use strict;
# this is our module
use CustomModule;
BEGIN {
# this will be executed before
# the rest of the code
unshift(@INC, "/home/dwilson");
}
print "In main bodyn";
print "=" x 25, "n";
print join("n", @INC);
We use the BEGIN block to place another
directory at the start of the ‘@INC’ array
( array index zero ) pushing the other
directories one position back. We do this
so that our additional directory is the
first one that is checked for the module.
The execution then moves back to the
top of the file and begins running the
code in its usual order and includes the
“CustomModule” before moving on to
the print statements. If you run this code
you will get a list of the directories in
‘@INC’ including our additional one, the
change we made is still effective.
Adding additional paths like this via
the BEGIN block is a common practice
when you either have a large number of
custom paths you wish to have included
or when you want to actually do
conditional inclusion of modules. As the
Perl Tutorial: Part 7PROGRAMMING
Can't locate NotExist.pm in @INC (@INC contains: /home/dwilson
/home/wanttogo /usr/lib/perl5/5.6.0/i386-linux /usr/lib/perl5/5.6.0
/usr/lib/perl5/site_perl/5.6.0/i386-linux /usr/lib/perl5/site_perl/5.6.0
/usr/lib/perl5/site_perl .) at module_error.pl line 5.
BEGIN failed--compilation aborted at begin_module.pl line 5.
Listing 4: Runtime errors
use warnings;
use strict;
our $fred = 'blah';
print "Current package is '", __PACKAGE__, "'n";
package Huey;
print "In package ", __PACKAGE__, "'n";
our $fred;
package Louey;
print "In package ", __PACKAGE__, "'n";
our $fred;
package Dewey;
print "In package ", __PACKAGE__, "'n";
our $fred;
Listing 3: Reusing variable names
you can run the code samples. If we
want to use the ‘roast_toast’ function at
the moment we need to qualify the call
with its full package name:
Toaster::roast_toast();
Although using the full package name as
a prefix to all external calls may seem
like just an inconvenience at the moment
once you begin to use multiple modules
with long names it will begin to have an
effect on the clarity of your code.
Another important reason to avoid using
this approach is with data access, or
encapsulation as it is often known as.
At the moment we can reach in and
change the value of any variable that we
like with no regard toward the internal
structure of the module, as an example
of this if we look at the ‘$toasting_time’
variable we can see that it is numeric
and is used internally in the module.
Look at the consequences of making a
change like this:
use Toaster;
$Toaster::toasting_time = U
"Thirty Seconds";
Toaster::roast_toast();
If we run without warnings with code
like this we will see strange behaviour as
Perl converts ‘$toasting_time’ into a
number from a string when ‘roast_toast’
uses it and the sleep time will become
erratic.
Instead of this direct action we should
use the functions provided to manipulate
any required variables, a practice called
data encapsulation, that is one of the
tenets of Object Orientated development
and a good design decision even in pro-
cedural code like ours.
By encapsulating data we protect our-
selves from tying our code too tightly
with the module’s own functions, all we
want to do is ‘roast_toast’, we do not
care if the time taken changes, we simply
want the action to be performed, in a
robust design the implementation should
be hidden to us.
We can address both of the above
concerns by using a feature of Perl’s
module system called ‘Exporter’. The
Exporter module allows module writers
to specify a list of the variables and
functions that they wish to expose to the
calling application so that they are
loaded into the current namespace. In
the example below we add some
additional Exporter related code to show
how little is needed before we start to
see the benefits:
#revised Toaster module
use strict;
use warnings;
package Toaster;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = U
qw($num_slots roast_toast);
our $VERSION = 1.50;
my $num_slots = 2;
my $toasting_time = 10;
sub roast_toast {
sleep $toasting_time;
print "Toast is donen";
return 0;
}
1;
The newly revised Toaster module ( with
free set of knives ) required just three
new lines included to take advantage of
these benefits, before we detail those
lines here is a small sample script that
can use the module:
use Toaster;
roast_toast();
This is an extremely simple example of
how all the explicit declarations can be
removed to cut down on the amount of
line noise in the code while retaining the
full functionality. If we try to change the
‘$toasting_time’ with the first example
below it fails:
use Toaster;
$toasting_time = 23;
The error we receive is “Global symbol
‘$toasting_time’ requires explicit
package name” due to no variable called
‘$toasting_time’ being present in the
‘main’ package and Toaster not
exporting its own ‘$toasting_time’. While
we can still modify the variable the same
way we did in previous examples using a
fully qualified package name this is
willfully ignoring the module writer’s
wishes and becomes more a case of
coder beware.
If the module author changes the way
the module is implemented ( which is
allowed as long as the public functions
are left alone ) then your code could
break and you would have no recourse.
There is probably a very good reason
why the module author did not expose
those variables and finding out why
could be painful.
Going back to our revised version of
the Toaster module we first pull in the
‘Exporter’ module and we then assign
Exporter to ‘@ISA’, this allows your
module to ‘inherit’ functionality from
the Exporter module. Inheritance is a
topic more related to object orientated
programming so we will gloss over the
details, for now just think of these two
lines as the code that enables your
module to export symbols.
The @EXPORT line controls which
functions and variables are to be
exported by default. Any entries in this
array will be exported to the calling
namespace when this module is ‘use’d.
If the caller only wants to pull out a
single function from your module and
keep the memory footprint of her own
application down then it is possible to
amend the ‘use Toaster;‘ code so that the
module only exports what is desired:
use Toaster qw(roast_toast);
This code sample will only import the
‘roast_toast’ function, if you now try and
modify the ‘$num_slots’ variable that
the module has in its ‘@EXPORT’ array
then you will get an error as it is no
longer available in this package.
use Toaster qw(roast_toast);
#this works
roast_toast();
#this fails with an error
$num_slots = 23;
Now we have covered the basic rules
and functionality of Exporting from one
module into an application, let’s look at
a slightly more complex scenario. If a
module has a basic level of functionality
that it always wants to provide, but it
also has some niche functions that are
only useful in specialized applications
but require too much memory to export
by default, rather than forcing the caller
to use fully qualified package names
65www.linux-magazine.com Dec 02 / Jan 03
PROGRAMMINGPerl Tutorial: Part 7
show you that the entry barrier is not as
high as it might seem we now move on
to one of the best examples of code reuse
on the Internet, CPAN.
Getting Modules
While Perl can stand feature for feature
with other modern programming
languages its true ‘killer app’ may be
CPAN (http://www.cpan.org), the
Comprehensive Perl Archive Network, a
large online repository of modules built
by the Perl community.
The modules in CPAN are themselves
good examples of why extra effort is
required to build a generic module .
However the effort is its own reward,
CPAN’s stock of code mostly originates
from coders “scratching their own itch”
and donating the code back to the
community to save other people from
reinventing the wheel. CPAN is one of
the more successful examples of the
“Cathedral” development methodology
whereby a pool of developers raise the
standard of the code base.
Once an author is registered on CPAN
they can begin the process of uploading
modules. Before a module can be
uploaded the name and purpose of the
module has to be announced to
‘modules@perl.org’ where the hard
working volunteers ensure there are no
duplications with existing work and the
module uses an appropriate namespace.
Once the module details have been
accepted the module is uploaded to the
server where it comes under the scrutiny
of the Perl QA Smoke testers.
The smoke testers are another group
of volunteers that donate processing
time on a variety of operating systems
and architectures, using batched scripts
new arrivals and updates on CPAN are
tested and the results are posted back to
CPAN showing which platforms the
module ran on. Finally the module is
propagated though the CPAN mirrors
until it becomes fully available every-
where.
Retrieving a Perl module can be done
in a number of ways:
• CPAN
• CPAN++
• manual install
• PPM
• Native package installer (apt-get, rpm
or similar)
The example given below shows the
typical install procedure for a module
that is being installed manually and then
we introduce you to the cpan shell that is
made available by the CPAN.pm module.
We will not be covering the other
methods of installation as they are not as
universally available.
Once the module’s ‘.tar.gz’ file is
downloaded from one of CPAN’s module
pages the following steps should be
taken to install it:
# extract module
$ tar -zxvf U
<modulename>-<version>.tar.gz
$ cd <modulename>-<version>
$ perl Makefile.PL
$ make
$ make test
$ make install
Stepping through the above example we
unpack the module and then change in
to its directory. Running ‘perl
Makefile.pl’ causes perl to generate a
Makefile for the module filling in many
of the required details with the
information Perl discovered about the
system when it was built and installed.
To show how much work this saves
consider that a Makefile.pl of 25 lines is
expanded to a ready for use Makefile of
over seven hundred lines.
We then run a ‘make’ to do any
building required for a module before
running the modules test harness with
‘make test’. Not all modules have a set of
tests to run. The Perl QA effort has
progressed to the point where all the
core modules have a test harness.
Although not having tests should
not stop you from using a module
their presence indicates a conscientious
author and an indication of robust code,
providing all the tests pass…
We then run ‘make install’ to perform
the work of installing the module in one
of the paths which Perl searches for its
libraries. An important often overlooked
detail is that this is the only step of
installing modules that actually requires
you to be root: all of the other stages can
be executed as an unprivileged user.
The extra privileges are needed
because it writes to directories that most
people will not have access to. Now that
you have seen the procedure for
66 Dec 02 / Jan 03 www.linux-magazine.com
and break some of the laws of good
design Exporter allows a second array to
be populated. This array is called
‘@EXPORT_OK’ and only exports what
the caller requests.
package Kettle;
require Exporter;
use strict;
use warnings;
our @ISA = qw(Exporter);
our @EXPORT = qw(boil);
our @EXPORT_OK = qw(whistle);
our $VERSION = 1.00;
my $boil_time = 2;
my $pints_held = 4;
sub boil {
print "Kettle has been $$
boiled...n";
}
sub whistle {
print "Whhhhhhheeeeeeeeen";
}
1;
The package above shows a very simple
implementation of a Kettle that has the
essential kettle function, ‘boil’ while also
providing the seldom requested ‘whistle’.
If we just ‘use Kettle’ then we only get
‘boil’ as that is the only element in the
‘@EXPORT’ array and if we explicitly
ask for ‘whistle’ with the ‘use Kettle
qw(whistle)‘ then we lose the ability to
‘boil’. To solve this problem Perl allows
you to ask for the entire ‘@EXPORT’
array and then any additional functions
that you would like:
use Kettle qw(:DEFAULT whistle);
boil();
whistle();
By using the special ‘:DEFAULT’ label to
import the values that are in the
‘@EXPORT’ array and also providing the
name of the features that you need in
your package you can make generic
modules that allow a large scope of
reuse. Working through the correct path
of code reuse has taken a lot more initial
effort than the simple copy and paste
approach does, but hopefully you will
have been convinced to do things
correctly by the additional power that
modules provide.
We have barely breached the surface
of Perl’s module system provides. To
Perl Tutorial: Part 7PROGRAMMING
installing a module by hand you can
appreciate the abstraction that installing
via CPAN provides. The other major
selling point of the CPAN approach is
dependency tracking.
When you try and install a module by
hand that depends upon additional
modules you must first install those
manually otherwise the install fails due
to unsatisfied dependencies. This could
take several iterations if the modules that
are listed as dependencies have further
dependencies of their own.
Installing via the CPAN module uses a
shell similar in many ways to bash,
including command completion and
history – if the required modules are
installed. The first time you invoke the
CPAN shell you will be prompted with a
list of configuration options that you will
be asked to confirm or edit. These
include which mirrors to download
from, where certain binaries are located
on the system and whether to
automatically follow dependencies.
To invoke the CPAN shell from the
command line you must type:
perl -MCPAN -e shell
And the prompt will change to ‘cpan>‘.
The invocation line causes the perl inter-
preter to load the module specified by
the upper case ‘-M’, in this case the
CPAN module while the ‘-e’ calls the
function ‘shell’ which has been exported
from the CPAN.pm module.
From within the cpan shell you can
easily search for and install additional
modules with a very important
advantage over installing them by hand,
CPAN.pm will track and install
dependencies for you.
Depending on the values you supplied
when you ran CPAN.pm for the first
time, this tracking dependencies would
be done either automatically without a
prompt, only after you answer yes to
install at a prompt or the module install
would fail. As you would expect the last
option is seldom chosen.
Navigating around the CPAN shell is
very simple once you have a grasp of a
few basic principles, if you are unsure of
the command required to carry out a
task then type ‘help’ at the prompt and it
will return a list of the valid commands
and what they do.
The commands are in three main
groups:
• Querying commands
• Module installation
• Meta-commands
The querying commands are the best
place to start as they are often the
commands you use the most, to view the
collection of modules under the XML
namespace type in ‘m /XML::/‘ and
press return, a list of all the modules will
scroll past along with some additional
details such as the author name and
module version. When you look along
the selection of XML modules you may
see a module that looks promising for
the task at hand, for example
XML::XPath.
Once you have found a module that
may be suitable you can install it by
issuing ‘install XML::XPath’ at the
prompt, the module will then be
downloaded to the machine and the
manual steps described above will be
run via the CPAN.pm module. If the
module has any tests defined for itself
then they will be run at the install and a
report of the successes and failures will
be shown.
If the module fails its tests then the
installation of the module will be
aborted. If the module passes its own
tests but fails because of unsatisfied
dependencies then CPAN.pm will go and
track down those dependencies and
install then going through as many
iterations of this as needed until either
the modules are all installed or one of
them fails.
Similar Code
When you have begun to use a number
of CPAN modules you may find that the
standard of code provided is high
enough that you would like to see what
else the author has contributed.
The author of ‘XML::XPath’, Matt
Sergeant, a Perl luminary responsible for
a large number of CPAN’s more popular
has an impressive collection of modules
that can be viewed without leaving the
comfort of the CPAN shell.
We rerun the search for the
‘XML::XPath’ module but this time as we
know the full name we do not use a reg-
ular expression search and instead we
enter ‘m XML::XPath’. ‘m’ is the keyword
that tells CPAN.pm we are searching for
a module, you can also use ‘a’, ‘b’ or ‘d’
to search for authors, bundles or distrib-
utions but those are out of the scope of
this article.
The ‘m XML::XPath’ command will
then go and get a list of all the modules
that are currently listed in the author’s
home directory and display them on
screen with some additional details such
as the files last update time, the version
number of the module and even the file
size of the complete module. From here
if we wanted to install another module
we could do a simple ‘install XML::SAX’
and the CPAN.pm module would take
care of it for us.
Now that we have shown you how to
install modules we’re going to show you
how to be a little more choosy in the
modules you actually download, to find
out more information than the name and
brief summary you can use the
CPAN.pm shell to retrieve and display
the modules own readme file. To do this
for XML::SAX you would type the
intuitive ‘readme XML::SAX’, CPAN.pm
will go and download the file and then
the pager you chose in the initialization
of the CPAN.pm module will be invoked
to read it.
The last installation example we will
show is a little different from the
previous ones as it applies to CPAN.pm
itself, whenever a new release of the
CPAN.pm module is issued CPAN detects
this the next time it is run and offers the
chance to upgrade. Although it may
seem a little strange to use CPAN.pm to
upgrade the CPAN.pm module, the
process is very reliable and requires very
little additional effort beyond a normal
module install.
After you have issued an ‘install
CPAN’ command and the module has
been downloaded and the tests run you
finish off the install by issuing a ‘reload
cpan’ command, the screen will have
a little process counter of dots appear
and a summary of the total number of
subroutines that have been reloaded by
CPAN.pm itself is shown marking the
successful completion of the upgrade.
When you have completed your work
in the CPAN shell to exit back to your
command shell just enter ‘q’ on a line by
itself and press return, the lock-file will
be removed and the CPAN shell will then
be closed. ■
67www.linux-magazine.com Dec 02 / Jan 03
PROGRAMMINGPerl Tutorial: Part 7

More Related Content

What's hot

PHP 5.3/6
PHP 5.3/6PHP 5.3/6
PHP 5.3/6
Thomas Weinert
 
Linux
LinuxLinux
WordPress Plugin Basics
WordPress Plugin BasicsWordPress Plugin Basics
WordPress Plugin Basics
Amanda Giles
 
PHP
PHPPHP
Wenger sf xin-barton
Wenger sf xin-bartonWenger sf xin-barton
Wenger sf xin-barton
ENUG
 
PHP Web Programming
PHP Web ProgrammingPHP Web Programming
PHP Web Programming
Muthuselvam RS
 
Makefiles Bioinfo
Makefiles BioinfoMakefiles Bioinfo
Makefiles Bioinfo
Giovanni Marco Dall'Olio
 
Introduction to Modern Perl
Introduction to Modern PerlIntroduction to Modern Perl
Introduction to Modern Perl
Dave Cross
 
Unit 1
Unit 1Unit 1
makefiles tutorial
makefiles tutorialmakefiles tutorial
makefiles tutorial
vsubhashini
 
Introduction to Makefile
Introduction to MakefileIntroduction to Makefile
Introduction to Makefile
Tusharadri Sarkar
 
Ch3 gnu make
Ch3 gnu makeCh3 gnu make
Ch3 gnu make
艾鍗科技
 
MYSQL
MYSQLMYSQL
MYSQL
ARJUN
 
Introduction to makefile
Introduction to makefileIntroduction to makefile
Introduction to makefile
Ray Song
 
Php
PhpPhp
Drupal 8's Multilingual APIs: Building for the Entire World
Drupal 8's Multilingual APIs: Building for the Entire WorldDrupal 8's Multilingual APIs: Building for the Entire World
Drupal 8's Multilingual APIs: Building for the Entire World
Christian López Espínola
 
Php1
Php1Php1
Php1
Reka
 
PHP Function
PHP Function PHP Function
PHP Function
Reber Novanta
 
Perl programming language
Perl programming languagePerl programming language
Perl programming language
Elie Obeid
 

What's hot (19)

PHP 5.3/6
PHP 5.3/6PHP 5.3/6
PHP 5.3/6
 
Linux
LinuxLinux
Linux
 
WordPress Plugin Basics
WordPress Plugin BasicsWordPress Plugin Basics
WordPress Plugin Basics
 
PHP
PHPPHP
PHP
 
Wenger sf xin-barton
Wenger sf xin-bartonWenger sf xin-barton
Wenger sf xin-barton
 
PHP Web Programming
PHP Web ProgrammingPHP Web Programming
PHP Web Programming
 
Makefiles Bioinfo
Makefiles BioinfoMakefiles Bioinfo
Makefiles Bioinfo
 
Introduction to Modern Perl
Introduction to Modern PerlIntroduction to Modern Perl
Introduction to Modern Perl
 
Unit 1
Unit 1Unit 1
Unit 1
 
makefiles tutorial
makefiles tutorialmakefiles tutorial
makefiles tutorial
 
Introduction to Makefile
Introduction to MakefileIntroduction to Makefile
Introduction to Makefile
 
Ch3 gnu make
Ch3 gnu makeCh3 gnu make
Ch3 gnu make
 
MYSQL
MYSQLMYSQL
MYSQL
 
Introduction to makefile
Introduction to makefileIntroduction to makefile
Introduction to makefile
 
Php
PhpPhp
Php
 
Drupal 8's Multilingual APIs: Building for the Entire World
Drupal 8's Multilingual APIs: Building for the Entire WorldDrupal 8's Multilingual APIs: Building for the Entire World
Drupal 8's Multilingual APIs: Building for the Entire World
 
Php1
Php1Php1
Php1
 
PHP Function
PHP Function PHP Function
PHP Function
 
Perl programming language
Perl programming languagePerl programming language
Perl programming language
 

Viewers also liked

Investigación - Acción
Investigación - AcciónInvestigación - Acción
Investigación - Acción
Luz Elena Morales Alvarado
 
Tha Total Elimination.Pt.1.html.doc.docx
Tha Total Elimination.Pt.1.html.doc.docxTha Total Elimination.Pt.1.html.doc.docx
Tha Total Elimination.Pt.1.html.doc.docx
MCDub
 
Criminal class loc's in ultra motion.Pt.3.Pic.doc
Criminal class loc's in ultra motion.Pt.3.Pic.docCriminal class loc's in ultra motion.Pt.3.Pic.doc
Criminal class loc's in ultra motion.Pt.3.Pic.doc
MCDub
 
Tha price of war.pt.3.newer.html.doc
Tha price of war.pt.3.newer.html.docTha price of war.pt.3.newer.html.doc
Tha price of war.pt.3.newer.html.doc
MCDub
 
vijaya
vijayavijaya
vijaya
Vijaya K
 
led filament bulb catalogue -new products
led filament bulb catalogue -new productsled filament bulb catalogue -new products
led filament bulb catalogue -new products
绮雯 罗
 
NTFS
NTFSNTFS
Maxwell walking tour
Maxwell walking tourMaxwell walking tour
Maxwell walking tour
ls234
 
HCA Branding_CS
HCA Branding_CSHCA Branding_CS
HCA Branding_CS
Naomi Anderson
 
Phần mềm Quản lý Bán hàng - 365
Phần mềm Quản lý Bán hàng - 365Phần mềm Quản lý Bán hàng - 365
Phần mềm Quản lý Bán hàng - 365
Minh Hoang
 
Hasselblad
HasselbladHasselblad
Hasselblad
Naomi Anderson
 
Environmental health&amp;safety
Environmental health&amp;safetyEnvironmental health&amp;safety
Environmental health&amp;safety
zhengzhou uniwin nail making machinery Co., ltd.
 
4260 CIMA Thinking the Unthinkable web b
4260 CIMA Thinking the Unthinkable web b4260 CIMA Thinking the Unthinkable web b
4260 CIMA Thinking the Unthinkable web b
Chris Langdon
 
Origen de la teoria de la administracion
Origen de la teoria de la administracionOrigen de la teoria de la administracion
Origen de la teoria de la administracion
Eden Rodríguez
 
Atvididade 1 "Conheça-me: Hermindo"
Atvididade 1 "Conheça-me: Hermindo"Atvididade 1 "Conheça-me: Hermindo"
Atvididade 1 "Conheça-me: Hermindo"
Hermindo_es
 
UBS_Center_Public_Paler_No4
UBS_Center_Public_Paler_No4UBS_Center_Public_Paler_No4
UBS_Center_Public_Paler_No4
Maura Wyler-Zerboni
 
Murad Camarad Wysinger C.D.Pt.1.html.docx
Murad Camarad Wysinger C.D.Pt.1.html.docxMurad Camarad Wysinger C.D.Pt.1.html.docx
Murad Camarad Wysinger C.D.Pt.1.html.docx
MCDub
 
Actividad 3.1 Presentación "Andradogía y Pedadogía"
Actividad 3.1 Presentación "Andradogía y Pedadogía"Actividad 3.1 Presentación "Andradogía y Pedadogía"
Actividad 3.1 Presentación "Andradogía y Pedadogía"
Jorge Vizcarra Figueroa
 
022916 bmo conference
022916 bmo conference022916 bmo conference
022916 bmo conference
Laura Hildred
 
Tha Price Of Health.Pt.1.newer.html.doc
Tha Price Of Health.Pt.1.newer.html.docTha Price Of Health.Pt.1.newer.html.doc
Tha Price Of Health.Pt.1.newer.html.doc
MCDub
 

Viewers also liked (20)

Investigación - Acción
Investigación - AcciónInvestigación - Acción
Investigación - Acción
 
Tha Total Elimination.Pt.1.html.doc.docx
Tha Total Elimination.Pt.1.html.doc.docxTha Total Elimination.Pt.1.html.doc.docx
Tha Total Elimination.Pt.1.html.doc.docx
 
Criminal class loc's in ultra motion.Pt.3.Pic.doc
Criminal class loc's in ultra motion.Pt.3.Pic.docCriminal class loc's in ultra motion.Pt.3.Pic.doc
Criminal class loc's in ultra motion.Pt.3.Pic.doc
 
Tha price of war.pt.3.newer.html.doc
Tha price of war.pt.3.newer.html.docTha price of war.pt.3.newer.html.doc
Tha price of war.pt.3.newer.html.doc
 
vijaya
vijayavijaya
vijaya
 
led filament bulb catalogue -new products
led filament bulb catalogue -new productsled filament bulb catalogue -new products
led filament bulb catalogue -new products
 
NTFS
NTFSNTFS
NTFS
 
Maxwell walking tour
Maxwell walking tourMaxwell walking tour
Maxwell walking tour
 
HCA Branding_CS
HCA Branding_CSHCA Branding_CS
HCA Branding_CS
 
Phần mềm Quản lý Bán hàng - 365
Phần mềm Quản lý Bán hàng - 365Phần mềm Quản lý Bán hàng - 365
Phần mềm Quản lý Bán hàng - 365
 
Hasselblad
HasselbladHasselblad
Hasselblad
 
Environmental health&amp;safety
Environmental health&amp;safetyEnvironmental health&amp;safety
Environmental health&amp;safety
 
4260 CIMA Thinking the Unthinkable web b
4260 CIMA Thinking the Unthinkable web b4260 CIMA Thinking the Unthinkable web b
4260 CIMA Thinking the Unthinkable web b
 
Origen de la teoria de la administracion
Origen de la teoria de la administracionOrigen de la teoria de la administracion
Origen de la teoria de la administracion
 
Atvididade 1 "Conheça-me: Hermindo"
Atvididade 1 "Conheça-me: Hermindo"Atvididade 1 "Conheça-me: Hermindo"
Atvididade 1 "Conheça-me: Hermindo"
 
UBS_Center_Public_Paler_No4
UBS_Center_Public_Paler_No4UBS_Center_Public_Paler_No4
UBS_Center_Public_Paler_No4
 
Murad Camarad Wysinger C.D.Pt.1.html.docx
Murad Camarad Wysinger C.D.Pt.1.html.docxMurad Camarad Wysinger C.D.Pt.1.html.docx
Murad Camarad Wysinger C.D.Pt.1.html.docx
 
Actividad 3.1 Presentación "Andradogía y Pedadogía"
Actividad 3.1 Presentación "Andradogía y Pedadogía"Actividad 3.1 Presentación "Andradogía y Pedadogía"
Actividad 3.1 Presentación "Andradogía y Pedadogía"
 
022916 bmo conference
022916 bmo conference022916 bmo conference
022916 bmo conference
 
Tha Price Of Health.Pt.1.newer.html.doc
Tha Price Of Health.Pt.1.newer.html.docTha Price Of Health.Pt.1.newer.html.doc
Tha Price Of Health.Pt.1.newer.html.doc
 

Similar to Perl_Part7

WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTHWEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
Bhavsingh Maloth
 
Perl_Part1
Perl_Part1Perl_Part1
Perl_Part1
Frank Booth
 
Perl_Part5
Perl_Part5Perl_Part5
Perl_Part5
Frank Booth
 
Tutorial perl programming basic eng ver
Tutorial perl programming basic eng verTutorial perl programming basic eng ver
Tutorial perl programming basic eng ver
Qrembiezs Intruder
 
web programming Unit VI PPT by Bhavsingh Maloth
web programming Unit VI PPT  by Bhavsingh Malothweb programming Unit VI PPT  by Bhavsingh Maloth
web programming Unit VI PPT by Bhavsingh Maloth
Bhavsingh Maloth
 
dylibencapsulation
dylibencapsulationdylibencapsulation
dylibencapsulation
Cole Herzog
 
Top laravel packages to install handpicked list from expert
Top laravel packages to install handpicked list from expertTop laravel packages to install handpicked list from expert
Top laravel packages to install handpicked list from expert
Katy Slemon
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2
Vishal Biyani
 
Class notes(week 7) on packages
Class notes(week 7) on packagesClass notes(week 7) on packages
Class notes(week 7) on packages
Kuntal Bhowmick
 
Bioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-filesBioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-files
Prof. Wim Van Criekinge
 
The Bund language
The Bund languageThe Bund language
The Bund language
Vladimir Ulogov
 
Migrating Puppet 3 to 4 -- Code Changes
Migrating Puppet 3 to 4 -- Code ChangesMigrating Puppet 3 to 4 -- Code Changes
Migrating Puppet 3 to 4 -- Code Changes
Gabriel Schuyler
 
Managing Perl Installations: A SysAdmin's View
Managing Perl Installations: A SysAdmin's ViewManaging Perl Installations: A SysAdmin's View
Managing Perl Installations: A SysAdmin's View
Baden Hughes
 
Java packages
Java packagesJava packages
Java packages
Jeffrey Quevedo
 
topic_perlcgi
topic_perlcgitopic_perlcgi
topic_perlcgi
tutorialsruby
 
topic_perlcgi
topic_perlcgitopic_perlcgi
topic_perlcgi
tutorialsruby
 
Functions in Python Syntax and working .
Functions in Python Syntax and working .Functions in Python Syntax and working .
Functions in Python Syntax and working .
tarunsharmaug23
 
Unit 1-introduction to perl
Unit 1-introduction to perlUnit 1-introduction to perl
Unit 1-introduction to perl
sana mateen
 
Aspect-oriented programming in Perl
Aspect-oriented programming in PerlAspect-oriented programming in Perl
Aspect-oriented programming in Perl
megakott
 
Packaging for the Maemo Platform
Packaging for the Maemo PlatformPackaging for the Maemo Platform
Packaging for the Maemo Platform
Jeremiah Foster
 

Similar to Perl_Part7 (20)

WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTHWEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
 
Perl_Part1
Perl_Part1Perl_Part1
Perl_Part1
 
Perl_Part5
Perl_Part5Perl_Part5
Perl_Part5
 
Tutorial perl programming basic eng ver
Tutorial perl programming basic eng verTutorial perl programming basic eng ver
Tutorial perl programming basic eng ver
 
web programming Unit VI PPT by Bhavsingh Maloth
web programming Unit VI PPT  by Bhavsingh Malothweb programming Unit VI PPT  by Bhavsingh Maloth
web programming Unit VI PPT by Bhavsingh Maloth
 
dylibencapsulation
dylibencapsulationdylibencapsulation
dylibencapsulation
 
Top laravel packages to install handpicked list from expert
Top laravel packages to install handpicked list from expertTop laravel packages to install handpicked list from expert
Top laravel packages to install handpicked list from expert
 
Learning puppet chapter 2
Learning puppet chapter 2Learning puppet chapter 2
Learning puppet chapter 2
 
Class notes(week 7) on packages
Class notes(week 7) on packagesClass notes(week 7) on packages
Class notes(week 7) on packages
 
Bioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-filesBioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-files
 
The Bund language
The Bund languageThe Bund language
The Bund language
 
Migrating Puppet 3 to 4 -- Code Changes
Migrating Puppet 3 to 4 -- Code ChangesMigrating Puppet 3 to 4 -- Code Changes
Migrating Puppet 3 to 4 -- Code Changes
 
Managing Perl Installations: A SysAdmin's View
Managing Perl Installations: A SysAdmin's ViewManaging Perl Installations: A SysAdmin's View
Managing Perl Installations: A SysAdmin's View
 
Java packages
Java packagesJava packages
Java packages
 
topic_perlcgi
topic_perlcgitopic_perlcgi
topic_perlcgi
 
topic_perlcgi
topic_perlcgitopic_perlcgi
topic_perlcgi
 
Functions in Python Syntax and working .
Functions in Python Syntax and working .Functions in Python Syntax and working .
Functions in Python Syntax and working .
 
Unit 1-introduction to perl
Unit 1-introduction to perlUnit 1-introduction to perl
Unit 1-introduction to perl
 
Aspect-oriented programming in Perl
Aspect-oriented programming in PerlAspect-oriented programming in Perl
Aspect-oriented programming in Perl
 
Packaging for the Maemo Platform
Packaging for the Maemo PlatformPackaging for the Maemo Platform
Packaging for the Maemo Platform
 

Perl_Part7

  • 1. In Perl parlance a ‘package’ is a way of specifying a namespace, before we examine the syntax of a package let’s look at what a namespace is and the benefits they can provide. A rose by any other name In essence a namespace is used to isolate variables and functions into separate “compartments” to help avoid name- space pollution and collision. Within a program all of the functions and variables (including filehandles) are from the ‘main’ package, to determine which package the currently executing code is in Perl provides the ‘__PACKAGE__’ constant: print "Current package is: '"; print __PACKAGE__, "'n"; The ‘__PACKAGE__’ constant cannot be placed within a double quoted string and still be interpolated, by including it in double quotes the literal value is returned instead. Creating a new package by using the ‘package’ function with the name of the package you wish to create (Listing 1). A package’s scope is terminated by the end of the file, exiting the block the package was declared in or declaring another package afterward, as shown in Listing 2. Using a namespace we can reuse variable names in each package using the ‘our’ key- word to declare the variables to exist with a specific value within a package (Listing 3). This code will compile and run but give warnings. Modules – Scratching Itches Now you have been introduced to how packages work you may be wishing you had stopped reading at the copy and paste coding section. Now that you have seen the cost of code re-use the right way we can introduce you to the benefits, namely building modules. A module is quite simply a package placed in a separate file, where the file name is the same as the package name with a ‘.pm’ suffix so that Perl readily recognizes the file as a “Perl Module”. The code below is from a file called Toaster.pm: #this should be placed in #a file called Toaster.pm package Toaster; our $VERSION = 1.00; my $num_slots = 2; my $toasting_time = 10; sub roast_toast { sleep $toasting_time; print "Toast is donen"; return 0; } 1; The first line of a module IS ALWAYS the package declaration, ensure the case of the name matches the file-name. The 62 Dec 02 / Jan 03 www.linux-magazine.com O nce your code begins to grow beyond a small script and into large applications you will often need to re-use small snippets, functions or even collections of functions that you have written in new applications. There are two main ways you can set about this re-use: • copy and paste • code abstraction Unlike most choices in Perl there is only one sensible way to do it. Copy and pasting code may seem like a quick and easy way to reproduce the functionality you need but it has a number of drawbacks that far out-weigh any temporary time-savings. The greatest of these issues is bug- fixing, if you find a bug (and it WILL happen) in a piece of code you have manually copied and pasted into multiple files then you will have to track down each and every occurrence of the code (Potentially even in files on different machines so a simple find and replace will not make the task any less arduous for you) and make the change numerous times. You will also find that you frequently make small incremental adjustments to the code to make it fit better to the task, so any enhancements will have to be copied too. If just one instance of the code is overlooked, then there are different solutions to the same problem. Fixing a bug in this manner will cost you far more than any time you saved by adopting this approach. Are you sure you fixed that bug everywhere? Now that we have covered the worst way of implementing code re-use let’s explain the principles behind the preferred methods, packages and modules. The commonly adopted approach to code reuse is to write functions and put them into a file in an accessible location. The functions within a file should be logically grouped together by purpose. Functions whose tasks have a similar theme are usually placed in the same file. To fit in with the festive season this month we are going to look at presents, well packages to be exact but you can still think of them as little bundles of coding joy.BY DEAN WILSON AND FRANK BOOTH Thinking In Line Noise Pre-wrapped Packages Perl Tutorial: Part 7PROGRAMMING #in the default package print "Current package is '", __PACKAGE__, "'n"; package Huey; print "In package ", __PACKAGE__, "'n"; package Louey; print "In package ", __PACKAGE__, "'n"; package Dewey; print "In package ", __PACKAGE__, "'n"; package main; print "In package ", __PACKAGE__, "'n"; Listing 1: __PACKAGE__
  • 2. module name should begin with an uppercase letter, as a rule only pragmas begin with a lowercase letter. In the Toaster module we declare two variables and a function. If you’re wondering what the ‘1;‘ line at the end of the code block is there for (in a real module this would be at the end of the file), it is required as all Perl modules must evaluate to ‘true’ when they’re compiled. Although the value of the last evalu- ated expression in the module would be returned this is not guaranteed to evalu- ate to ‘true’ as we can see by the function ‘roast_toast’ returning ‘0’ so for clarity and simplicity we explicitly return ‘1’ to ensure a correct compile and load. Loading the Toaster We now need to actually load the module into our perl program when we run the application so we can access the functionality it provides. Perl tracks the modules it has available for use by storing a list of paths as a list within which it looks for ‘.pm’ files. This list is known as ‘@INC’ and is available within perl itself for modification. Before we move on to showing you how to add your own directories let’s show two possible ways to display the default value of ‘@INC’. The first way to do this is by allowing Perl itself to do the work and show us where it searches: perl -V You will then be shown a number of details that describe many of the options that this Perl interpreter was compiled with. Underneath those details you will find a section that resembles: /usr/lib/perl5/5.6.0/i386-linux /usr/lib/perl5/5.6.0 /usr/lib/perl5/site_perl/5.6.0/U i386-linux /usr/lib/perl5/site_perl/5.6.0 /usr/lib/perl5/site_perl This information shows the default locations that perl will search when you have a ‘use’ statement in your code. Two items of interest are that many of the site directories have the version number contained within them allowing many versions of Perl to live happily on the same machine while still allowing easy identification of which version the modules belong to. The machine this was written on has five versions for backwards compatibility testing. The second item of interest is that the current directory ‘.’ is included by default. The second way to show the searched directories by using actual Perl code, from the command line you can issue: perl U -we 'print map { "$_n" } @INC;' To generate a list of the default directories that are printed to screen in this format: /usr/lib/perl5/5.6.0/i386-linux /usr/lib/perl5/5.6.0 /usr/lib/perl5/site_perl/5.6.0/U i386-linux /usr/lib/perl5/site_perl/5.6.0 /usr/lib/perl5/site_perl Recognize the directories it returns? This is the same information that the Perl interpreter itself told us about but the list is available from within Perl itself. Now we have provided a number of different techniques to retrieve and display the current and default values of ‘@INC’ we will move on and step though the list of ways to coerce Perl into looking in additional locations for additional modules including: • ‘-I’ command line switch • Modifying @INC in a BEGIN block • ‘use lib’ pragma The ‘-I’ method can be a very long-winded way of specifying additional directories and suffers from an important drawback: You have to remember to add it with every invocation of the program. # nvoke 'buildscript with # build/directory added to @INC perl -I build/directory U buildscript.pl In the above example of ‘-I’ we add the ‘build/directory/‘ to the ‘@INC’ list of the ‘buildscript.pl’ script. Where ‘-I’ comes into its element is when used in quick prototyping of very small projects, however once your requirements grow to the level where you need to specify multiple additional include directories you will begin to see the use of ‘-I’ as a limiting factor to how far your project can scale. We have not yet covered Perl’s special blocks such as BEGIN or END in this article but it is worth mentioning this technique at this stage as a refer- ence, although it is an oversimplification at a basic level if you have a BEGIN block in your code then its contents will be executed before anything else in the application is, including module loading. # notice this should be executed # first as it is before the # BEGIN block print "Normal Hellon"; BEGIN { # this sections runs first print "I'm run firstn"; } 63www.linux-magazine.com Dec 02 / Jan 03 PROGRAMMINGPerl Tutorial: Part 7 #in the default package print "Current package is '", __PACKAGE__, "'n"; # Exiting the block the # package was declared in { package Larry; print "In package ", __PACKAGE__, "'n"; } # Back to main package print "In package ", __PACKAGE__, "'n"; # Closing a package by # declaring a new package package Moe; print "In package ", __PACKAGE__, "'n"; # in this case the new # package is main again. package main; print "In package ", __PACKAGE__, "'n"; # Package terminated by # end of file. package Curly; print "In package ", __PACKAGE__, "'n"; Listing 2: Exiting the block
  • 3. BEGIN block is inside the Perl application it is possible to use Perl functions to alter the values in ‘@INC’ and so dynamically build- ing a list of directories is made simple with very little additional code or complexity required. The last of the more common approaches is using a pragma known as ‘use lib’ to specify the desired additions. Using this method is actually one of the simpler ways of specifying new paths, it’s as sim- ple as adding a call to the pragma at the top of your program: # !/usr/bin/perl -w use strict; use lib("/home/dwilson", U "/home/wanttogo"); use CustomModule; print "In main bodyn"; print "=" x 25, "n"; print join("n", @INC); When this code snippet is run the two additional directories are added to ‘@INC’ and then made available to the rest of the program. If you ‘use’ modules like this then you should always specify the name of the module in a ‘use’ state- ment AFTER the ‘use lib’ otherwise you will get run-time errors, as shown in Listing 4. Although we did not define our own BEGIN block in this code the module loading is still done at this phase and the error is caught before we go on any fur- ther. The ease of use provided by ‘use lib’ is significant and has a very low learning curve that allows it to be used in most of the cases where you would want to add additional paths, once you find yourself needing more flexibility than this you will often have to resort back to using BEGIN blocks with all the power they provide, albeit at the cost of greater complexity. Invoking the mighty toaster After wading through the coverage of how to create your own packaged name- space and then reading the details surrounding the loading of modules you are probably getting the itch to test your new found knowledge with some concrete code examples. The examples throughout the rest of this section assume that you have the “Toaster” module in one of the locations specified in ‘@INC’ so if you have skipped past the previous text you are going to be unable to progress until you have gone back and read it all. You can test that you can access “Toaster” correctly by running: perl -MToaster -e 'print U $Toaster::VERSION, "n";' This should return ‘1’, if you see “Can’t locate Toaster.pm in @INC” then the module is not in the ‘@INC’ path and you need to amend your configuration as per the instructions given above ( in the “Loading the Toaster” section ) before 64 Dec 02 / Jan 03 www.linux-magazine.com As you would expect, it has a corresponding END block. The code contained within the block is ALWAYS run just before the program finishes its own execution. print "running happily in "; print __PACKAGE__, "n"; END { print "exiting at "; print scalar localtime(); print "n";' } Although we will delay the detailed look at the full range of functionality these two block types provide the more com- mon uses of these blocks make sense even without knowing all their intimate details, END blocks are ideal places to put clean up or summary code and BEGIN blocks are a perfect place to alter ‘@INC’ as shown below: # !/usr/bin/perl -w use warnings; use strict; # this is our module use CustomModule; BEGIN { # this will be executed before # the rest of the code unshift(@INC, "/home/dwilson"); } print "In main bodyn"; print "=" x 25, "n"; print join("n", @INC); We use the BEGIN block to place another directory at the start of the ‘@INC’ array ( array index zero ) pushing the other directories one position back. We do this so that our additional directory is the first one that is checked for the module. The execution then moves back to the top of the file and begins running the code in its usual order and includes the “CustomModule” before moving on to the print statements. If you run this code you will get a list of the directories in ‘@INC’ including our additional one, the change we made is still effective. Adding additional paths like this via the BEGIN block is a common practice when you either have a large number of custom paths you wish to have included or when you want to actually do conditional inclusion of modules. As the Perl Tutorial: Part 7PROGRAMMING Can't locate NotExist.pm in @INC (@INC contains: /home/dwilson /home/wanttogo /usr/lib/perl5/5.6.0/i386-linux /usr/lib/perl5/5.6.0 /usr/lib/perl5/site_perl/5.6.0/i386-linux /usr/lib/perl5/site_perl/5.6.0 /usr/lib/perl5/site_perl .) at module_error.pl line 5. BEGIN failed--compilation aborted at begin_module.pl line 5. Listing 4: Runtime errors use warnings; use strict; our $fred = 'blah'; print "Current package is '", __PACKAGE__, "'n"; package Huey; print "In package ", __PACKAGE__, "'n"; our $fred; package Louey; print "In package ", __PACKAGE__, "'n"; our $fred; package Dewey; print "In package ", __PACKAGE__, "'n"; our $fred; Listing 3: Reusing variable names
  • 4. you can run the code samples. If we want to use the ‘roast_toast’ function at the moment we need to qualify the call with its full package name: Toaster::roast_toast(); Although using the full package name as a prefix to all external calls may seem like just an inconvenience at the moment once you begin to use multiple modules with long names it will begin to have an effect on the clarity of your code. Another important reason to avoid using this approach is with data access, or encapsulation as it is often known as. At the moment we can reach in and change the value of any variable that we like with no regard toward the internal structure of the module, as an example of this if we look at the ‘$toasting_time’ variable we can see that it is numeric and is used internally in the module. Look at the consequences of making a change like this: use Toaster; $Toaster::toasting_time = U "Thirty Seconds"; Toaster::roast_toast(); If we run without warnings with code like this we will see strange behaviour as Perl converts ‘$toasting_time’ into a number from a string when ‘roast_toast’ uses it and the sleep time will become erratic. Instead of this direct action we should use the functions provided to manipulate any required variables, a practice called data encapsulation, that is one of the tenets of Object Orientated development and a good design decision even in pro- cedural code like ours. By encapsulating data we protect our- selves from tying our code too tightly with the module’s own functions, all we want to do is ‘roast_toast’, we do not care if the time taken changes, we simply want the action to be performed, in a robust design the implementation should be hidden to us. We can address both of the above concerns by using a feature of Perl’s module system called ‘Exporter’. The Exporter module allows module writers to specify a list of the variables and functions that they wish to expose to the calling application so that they are loaded into the current namespace. In the example below we add some additional Exporter related code to show how little is needed before we start to see the benefits: #revised Toaster module use strict; use warnings; package Toaster; require Exporter; our @ISA = qw(Exporter); our @EXPORT = U qw($num_slots roast_toast); our $VERSION = 1.50; my $num_slots = 2; my $toasting_time = 10; sub roast_toast { sleep $toasting_time; print "Toast is donen"; return 0; } 1; The newly revised Toaster module ( with free set of knives ) required just three new lines included to take advantage of these benefits, before we detail those lines here is a small sample script that can use the module: use Toaster; roast_toast(); This is an extremely simple example of how all the explicit declarations can be removed to cut down on the amount of line noise in the code while retaining the full functionality. If we try to change the ‘$toasting_time’ with the first example below it fails: use Toaster; $toasting_time = 23; The error we receive is “Global symbol ‘$toasting_time’ requires explicit package name” due to no variable called ‘$toasting_time’ being present in the ‘main’ package and Toaster not exporting its own ‘$toasting_time’. While we can still modify the variable the same way we did in previous examples using a fully qualified package name this is willfully ignoring the module writer’s wishes and becomes more a case of coder beware. If the module author changes the way the module is implemented ( which is allowed as long as the public functions are left alone ) then your code could break and you would have no recourse. There is probably a very good reason why the module author did not expose those variables and finding out why could be painful. Going back to our revised version of the Toaster module we first pull in the ‘Exporter’ module and we then assign Exporter to ‘@ISA’, this allows your module to ‘inherit’ functionality from the Exporter module. Inheritance is a topic more related to object orientated programming so we will gloss over the details, for now just think of these two lines as the code that enables your module to export symbols. The @EXPORT line controls which functions and variables are to be exported by default. Any entries in this array will be exported to the calling namespace when this module is ‘use’d. If the caller only wants to pull out a single function from your module and keep the memory footprint of her own application down then it is possible to amend the ‘use Toaster;‘ code so that the module only exports what is desired: use Toaster qw(roast_toast); This code sample will only import the ‘roast_toast’ function, if you now try and modify the ‘$num_slots’ variable that the module has in its ‘@EXPORT’ array then you will get an error as it is no longer available in this package. use Toaster qw(roast_toast); #this works roast_toast(); #this fails with an error $num_slots = 23; Now we have covered the basic rules and functionality of Exporting from one module into an application, let’s look at a slightly more complex scenario. If a module has a basic level of functionality that it always wants to provide, but it also has some niche functions that are only useful in specialized applications but require too much memory to export by default, rather than forcing the caller to use fully qualified package names 65www.linux-magazine.com Dec 02 / Jan 03 PROGRAMMINGPerl Tutorial: Part 7
  • 5. show you that the entry barrier is not as high as it might seem we now move on to one of the best examples of code reuse on the Internet, CPAN. Getting Modules While Perl can stand feature for feature with other modern programming languages its true ‘killer app’ may be CPAN (http://www.cpan.org), the Comprehensive Perl Archive Network, a large online repository of modules built by the Perl community. The modules in CPAN are themselves good examples of why extra effort is required to build a generic module . However the effort is its own reward, CPAN’s stock of code mostly originates from coders “scratching their own itch” and donating the code back to the community to save other people from reinventing the wheel. CPAN is one of the more successful examples of the “Cathedral” development methodology whereby a pool of developers raise the standard of the code base. Once an author is registered on CPAN they can begin the process of uploading modules. Before a module can be uploaded the name and purpose of the module has to be announced to ‘modules@perl.org’ where the hard working volunteers ensure there are no duplications with existing work and the module uses an appropriate namespace. Once the module details have been accepted the module is uploaded to the server where it comes under the scrutiny of the Perl QA Smoke testers. The smoke testers are another group of volunteers that donate processing time on a variety of operating systems and architectures, using batched scripts new arrivals and updates on CPAN are tested and the results are posted back to CPAN showing which platforms the module ran on. Finally the module is propagated though the CPAN mirrors until it becomes fully available every- where. Retrieving a Perl module can be done in a number of ways: • CPAN • CPAN++ • manual install • PPM • Native package installer (apt-get, rpm or similar) The example given below shows the typical install procedure for a module that is being installed manually and then we introduce you to the cpan shell that is made available by the CPAN.pm module. We will not be covering the other methods of installation as they are not as universally available. Once the module’s ‘.tar.gz’ file is downloaded from one of CPAN’s module pages the following steps should be taken to install it: # extract module $ tar -zxvf U <modulename>-<version>.tar.gz $ cd <modulename>-<version> $ perl Makefile.PL $ make $ make test $ make install Stepping through the above example we unpack the module and then change in to its directory. Running ‘perl Makefile.pl’ causes perl to generate a Makefile for the module filling in many of the required details with the information Perl discovered about the system when it was built and installed. To show how much work this saves consider that a Makefile.pl of 25 lines is expanded to a ready for use Makefile of over seven hundred lines. We then run a ‘make’ to do any building required for a module before running the modules test harness with ‘make test’. Not all modules have a set of tests to run. The Perl QA effort has progressed to the point where all the core modules have a test harness. Although not having tests should not stop you from using a module their presence indicates a conscientious author and an indication of robust code, providing all the tests pass… We then run ‘make install’ to perform the work of installing the module in one of the paths which Perl searches for its libraries. An important often overlooked detail is that this is the only step of installing modules that actually requires you to be root: all of the other stages can be executed as an unprivileged user. The extra privileges are needed because it writes to directories that most people will not have access to. Now that you have seen the procedure for 66 Dec 02 / Jan 03 www.linux-magazine.com and break some of the laws of good design Exporter allows a second array to be populated. This array is called ‘@EXPORT_OK’ and only exports what the caller requests. package Kettle; require Exporter; use strict; use warnings; our @ISA = qw(Exporter); our @EXPORT = qw(boil); our @EXPORT_OK = qw(whistle); our $VERSION = 1.00; my $boil_time = 2; my $pints_held = 4; sub boil { print "Kettle has been $$ boiled...n"; } sub whistle { print "Whhhhhhheeeeeeeeen"; } 1; The package above shows a very simple implementation of a Kettle that has the essential kettle function, ‘boil’ while also providing the seldom requested ‘whistle’. If we just ‘use Kettle’ then we only get ‘boil’ as that is the only element in the ‘@EXPORT’ array and if we explicitly ask for ‘whistle’ with the ‘use Kettle qw(whistle)‘ then we lose the ability to ‘boil’. To solve this problem Perl allows you to ask for the entire ‘@EXPORT’ array and then any additional functions that you would like: use Kettle qw(:DEFAULT whistle); boil(); whistle(); By using the special ‘:DEFAULT’ label to import the values that are in the ‘@EXPORT’ array and also providing the name of the features that you need in your package you can make generic modules that allow a large scope of reuse. Working through the correct path of code reuse has taken a lot more initial effort than the simple copy and paste approach does, but hopefully you will have been convinced to do things correctly by the additional power that modules provide. We have barely breached the surface of Perl’s module system provides. To Perl Tutorial: Part 7PROGRAMMING
  • 6. installing a module by hand you can appreciate the abstraction that installing via CPAN provides. The other major selling point of the CPAN approach is dependency tracking. When you try and install a module by hand that depends upon additional modules you must first install those manually otherwise the install fails due to unsatisfied dependencies. This could take several iterations if the modules that are listed as dependencies have further dependencies of their own. Installing via the CPAN module uses a shell similar in many ways to bash, including command completion and history – if the required modules are installed. The first time you invoke the CPAN shell you will be prompted with a list of configuration options that you will be asked to confirm or edit. These include which mirrors to download from, where certain binaries are located on the system and whether to automatically follow dependencies. To invoke the CPAN shell from the command line you must type: perl -MCPAN -e shell And the prompt will change to ‘cpan>‘. The invocation line causes the perl inter- preter to load the module specified by the upper case ‘-M’, in this case the CPAN module while the ‘-e’ calls the function ‘shell’ which has been exported from the CPAN.pm module. From within the cpan shell you can easily search for and install additional modules with a very important advantage over installing them by hand, CPAN.pm will track and install dependencies for you. Depending on the values you supplied when you ran CPAN.pm for the first time, this tracking dependencies would be done either automatically without a prompt, only after you answer yes to install at a prompt or the module install would fail. As you would expect the last option is seldom chosen. Navigating around the CPAN shell is very simple once you have a grasp of a few basic principles, if you are unsure of the command required to carry out a task then type ‘help’ at the prompt and it will return a list of the valid commands and what they do. The commands are in three main groups: • Querying commands • Module installation • Meta-commands The querying commands are the best place to start as they are often the commands you use the most, to view the collection of modules under the XML namespace type in ‘m /XML::/‘ and press return, a list of all the modules will scroll past along with some additional details such as the author name and module version. When you look along the selection of XML modules you may see a module that looks promising for the task at hand, for example XML::XPath. Once you have found a module that may be suitable you can install it by issuing ‘install XML::XPath’ at the prompt, the module will then be downloaded to the machine and the manual steps described above will be run via the CPAN.pm module. If the module has any tests defined for itself then they will be run at the install and a report of the successes and failures will be shown. If the module fails its tests then the installation of the module will be aborted. If the module passes its own tests but fails because of unsatisfied dependencies then CPAN.pm will go and track down those dependencies and install then going through as many iterations of this as needed until either the modules are all installed or one of them fails. Similar Code When you have begun to use a number of CPAN modules you may find that the standard of code provided is high enough that you would like to see what else the author has contributed. The author of ‘XML::XPath’, Matt Sergeant, a Perl luminary responsible for a large number of CPAN’s more popular has an impressive collection of modules that can be viewed without leaving the comfort of the CPAN shell. We rerun the search for the ‘XML::XPath’ module but this time as we know the full name we do not use a reg- ular expression search and instead we enter ‘m XML::XPath’. ‘m’ is the keyword that tells CPAN.pm we are searching for a module, you can also use ‘a’, ‘b’ or ‘d’ to search for authors, bundles or distrib- utions but those are out of the scope of this article. The ‘m XML::XPath’ command will then go and get a list of all the modules that are currently listed in the author’s home directory and display them on screen with some additional details such as the files last update time, the version number of the module and even the file size of the complete module. From here if we wanted to install another module we could do a simple ‘install XML::SAX’ and the CPAN.pm module would take care of it for us. Now that we have shown you how to install modules we’re going to show you how to be a little more choosy in the modules you actually download, to find out more information than the name and brief summary you can use the CPAN.pm shell to retrieve and display the modules own readme file. To do this for XML::SAX you would type the intuitive ‘readme XML::SAX’, CPAN.pm will go and download the file and then the pager you chose in the initialization of the CPAN.pm module will be invoked to read it. The last installation example we will show is a little different from the previous ones as it applies to CPAN.pm itself, whenever a new release of the CPAN.pm module is issued CPAN detects this the next time it is run and offers the chance to upgrade. Although it may seem a little strange to use CPAN.pm to upgrade the CPAN.pm module, the process is very reliable and requires very little additional effort beyond a normal module install. After you have issued an ‘install CPAN’ command and the module has been downloaded and the tests run you finish off the install by issuing a ‘reload cpan’ command, the screen will have a little process counter of dots appear and a summary of the total number of subroutines that have been reloaded by CPAN.pm itself is shown marking the successful completion of the upgrade. When you have completed your work in the CPAN shell to exit back to your command shell just enter ‘q’ on a line by itself and press return, the lock-file will be removed and the CPAN shell will then be closed. ■ 67www.linux-magazine.com Dec 02 / Jan 03 PROGRAMMINGPerl Tutorial: Part 7