Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
Welcome to the Monastery
 
PerlMonks

Simple Module Tutorial

by tachyon (Chancellor)
 | Log in | Create a new user | The Monastery Gates | Super Search | 
 | Seekers of Perl Wisdom | Meditations | PerlMonks Discussion | 
 | Obfuscation | Reviews | Cool Uses For Perl | Perl News | Q&A | Tutorials | 
 | Poetry | Recent Threads | Newest Nodes | Donate | What's New | 

on Aug 06, 2001 at 01:30 UTC ( #102347=perltutorial: print w/ replies, xml ) Need Help??

So you find the Perl docs on modules a bit confusing? OK here is the world's simplest Perl module domonstrating all the salient features of Exporter and a script that uses this module. We also give a short rundown on @INC and finish with a note on using warnings and modules. Here is the module code.

MyModule.pm

package MyModule; use strict; use Exporter; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); $VERSION = 1.00; @ISA = qw(Exporter); @EXPORT = (); @EXPORT_OK = qw(func1 func2); %EXPORT_TAGS = ( DEFAULT => [qw(&func1)], Both => [qw(&func1 &func2)]); sub func1 { return reverse @_ } sub func2 { return map{ uc }@_ } 1;

First we get a namespace by declaring a package name. This helps ensure our module's functions and variables remain separate from any script that uses it.

Use strict is a very good idea for modules to restrict the use of global variables. See use strict warnings and diagnostics or die for more details.

We need to use the Exporter module to export our functions from the MyModule:: namespace into the main:: namespace to make them available to scripts that 'use' MyModule.

We pacify strict with the use vars declaration of some variables. We can use an 'our' declaration in 5.6+

We now set a $VERSION number and make Exporter part of MyModule using the @ISA. See perlboot for all the gory details on what @ISA is or just use it as shown.

@EXPORT contains a list of functions that we export by default, in this case nothing. Generally the less you export by default using @EXPORT the better. This avoids accidentally clashing with functions defined in the script using the module. If a script wants a function let it ask.

@EXPORT_OK contains a list of functions that we export on demand so we export &func1 &func2 only if specifically requested to. Use this in preference to just blindly exporting functions via @EXPORT. You can also export variables like $CONFIG provided they are globals not lexicals scoped with my (read declare them with our or use vars).

%EXPORT_TAGS. For convenience we define two sets of export tags. The ':DEFAULT' tag exports only &func1; the ':Both' tag exports both &func1 &func2. This hash stores labels pointing to array references. In this case the arrays are anonymous.

We need the 1; at the end because when a module loads Perl checks to see that the module returns a true value to ensure it loaded OK. You could put any true value at the end (see Code::Police) but 1 is the convention.

MyScript.pl (A simple script to use MyModule)

#!/usr/bin/perl -w use strict; # you may need to set @INC here (see below) my @list = qw (J u s t ~ A n o t h e r ~ P e r l ~ H a c k e r !); # case 1 # use MyModule; # print func1(@list),"\n"; # print func2(@list),"\n"; # case 2 # use MyModule qw(&func1); # print func1(@list),"\n"; # print MyModule::func2(@list),"\n"; # case 3 # use MyModule qw(:DEFAULT); # print func1(@list),"\n"; # print func2(@list),"\n"; # case 4 # use MyModule qw(:Both); # print func1(@list),"\n"; # print func2(@list),"\n";

We use MyModule in MyScript.pl as shown. Uncomment the examples to see what happens. Just uncomment one at a time.

Case 1: Because our module exports nothing by default we get errors as &funct1 and &funct2 have not been exported thus do not exist in the main:: namespace of the script.

Case 2: This works OK. We ask our module to export the &func1 so we can use it. Although &func2 was not exported we reference it with its full package name so this works OK.

Case 3: The ':DEFAULT' tag *should* export &func1 so you might expect the error here to concern a missing &func2. In fact Perl complains about &func1. Hmm, what is going on here. The DEFAULT tag name is special and is automatically set in our modules %EXPORT_TAGS hash like this DEFAULT => \@EXPORT.

Case 4: We specified the export of both our functions with the ':Both' thus this works.

A note on @INC

When you issue a use MyModule; directive perl searchs the @INC array for a module with the correct name. @INC usually contains:

/perl/lib 
/perl/site/lib
.

The . directory (dot dir) is the current working directory. CORE modules are installed under perl/lib whereas non-CORE modules install under perl/site/lib. You can add directories to the module search path in @INC like this:

BEGIN { push @INC, '/my/dir' } # or BEGIN { unshift @INC, '/my/dir' } # or use lib '/my/dir';

We need to use a BEGIN block to shift values into @INC at compile time as this is when perl checks for modules. If you wait until the script is comiled it is too late and perl will throw an exception saying it can't find MyModule in @INC... The difference between pushing a value and unshifting a value into @INC is that perl searches the @INC array for the module starting with the first dir in that array. Thus is you have a MyModule in /perl/lib/ and another in /perl/site/lib/ and another in ./ the one in /perl/lib will be found first and thus the one used. The use lib pragma effectively does the same as the BEGIN { unshift @INC, $dir } block - see perlman:lib:lib for full specifics.

What use Foo::Bar means

use Foo::Bar does not mean look for a module called "Foo::Bar.pm" in the @INC directories. It means search @INC for a *subdir* called "Foo" and a *module* called "Bar.pm".

Now once we have "use'd" a module its functions are available via the fully specified &PACKAGE::FUNCTION syntax. When we say &Foo::Bar::some_func we are refering to the *package name* not the (dir::)file name that we used in the use. This allows you to have many package names in one use'd file. In practice the names are usually the same.

use Warnings;

You should test your module with warnings enabled as this will pick up many subtle (and not so subtle :-) errors. You can activate warnings using the -w flag in the script you use to test the module. If you add use warnings to the module then your module will require Perl 5.6+ as this was not available before then. If you put $^W++ at the top of the module then you will globally enable warnings - this may break *other modules* a script may be using in addition to your module so is rather antisocial. An expert coder here called tye tests with warnings but does not include them directly in his/her modules.

Hope this explains how it works.

cheers

tachyon

Update

Fixed a typo and added a few comments. Thanks to John M. Dlugosz. Rewrote and restyled tute for compatibility with versions of Perl < 5.6 thanks to crazyinsomniac. Also thanks to tye for reminding me that $^W++ is globally scoped and a bit antisocial for a module.

s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Comment on Simple Module Tutorial
Select or Download Code
Re: Simple Module Tutorial
by John M. Dlugosz (Monsignor) on Aug 06, 2001 at 04:30 UTC
    Very nice, getting everything into a short page like that. But, I have a few comments:

    Are you sure you want to make $VERSION a float, rather than a v-string? And if so, illustrate the three-digit convention (e.g. 5.005_001 for version 5.5.1).

    I'm also shocked that your pm file doesn't use strict!

    I would also suggest adding a comment to the 1; line, saying that this means "loaded OK".

    —John

[reply]
[d/l]
[select]

      Thanks John I've updated the text a bit in line with your suggestions. Forgot the strict in the module! Oops it is back in its rightful place right at the top. I just used the simple $VERSION numbering because this is a simple tute :-) Here is an excerpt from the Exporter manpage for those interested.

      Module Version Checking The Exporter module will convert an attempt to import a number from a module into a call to $module_name->require_version($value). This can be used to validate that the version of the module being used is greater than or equal to the required version. The Exporter module supplies a default require_version method which checks the value of $VERSION in the exporting module. Since the default require_version method treats the $VERSION number as a simple numeric value it will regard version 1.10 as lower than 1.9. For this reason it is strongly recommended that you use numbers with at least two decimal places, e.g., 1.09.

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

[reply]
[d/l]
        Yea, I just posted a tutorial on VERSION.

        For compatibility with mixing decimals and v-strings, the built-in UNIVERSAL::require_version uses three decimal digits per part.

        If you have $MyModule::VERSION= 1.12; (a decimal number) and do a use MyModule 1.20.1 qw/bar/, it will tell you that the module 1.120 and you asked for 1.020, so that's OK. You expected 1.20 to be greater than 1.12, not-OK.

        —John

[reply]
[d/l]
(tye)Re: Simple Module Tutorial
by tye (Archbishop) on Aug 06, 2001 at 22:09 UTC

    $W++ will only give you run-time warnings and will affect other packages. Personally, I don't turn on warnings in modules that I write but I do make a point of testing them with warnings turned on (by putting "#!/usr/bin/perl -w" at the top of my test scripts).

            - tye (but my friends call me "Tye")
[reply]
[d/l]

      Thanks I changed it from the lexically scoped 'use warnings;' so that this is applicable to versions < 5.6. but as it adds little value to the tutorial and has the unwanted side effects you point out I have just deleted it - saves a few lines of dubious value. I'll add a note on testing with warnings when I have a moment.

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

[reply]
Re: Simple Module Tutorial
by beretboy (Chaplain) on Aug 18, 2001 at 15:07 UTC
    Exellent tutorial ++! I have never understood the writing of modules till now

    "Sanity is the playground of the unimaginative" -Unknown
[reply]
      Fantastic stuff - I just converted a full script into a module (and added some bits) and it worked 1st time - WITH NO DEBUGGING REQUIRED (and yes - I am using strict)!!! I was very scared of modules before but now feel like I could write a hundred. Thanks very much for this - invaluable tutorial for a newbie like me :))))))
[reply]
Re: Simple Module Tutorial
by Jaap (Curate) on Jul 22, 2002 at 09:35 UTC
    This is a nice tutorial tachyon. Are you considering writing a more advanced tutorial on modules (combined with OO)?

    Especially, what a GOOD module looks like. Should we use carp, dynaloader and what not?
[reply]
Re: Simple Module Tutorial
by gawatkins (Monsignor) on Apr 10, 2003 at 11:44 UTC

    Great Tutorial, It helped to clear up the muddy water created by my Perl Black Book.

    Thanks again,

    Greg W.

[reply]
Re: Simple Module Tutorial
by johnnywang (Priest) on Aug 09, 2004 at 22:58 UTC
    Quite some years have gone by since the inital post, just want to point out that "use vars" is now considered deprecated, instead, "our" is prefered. Another already mentioned point is not to use @EXPORT too much. So my basic module is like the following (I have a emacs function to output this):
    package MyModule; use strict; use Exporter qw(import); our $VERSION = 1.00; our @ISA = qw(Exporter); our @EXPORT_OK = qw(func1 func2); our %EXPORT_TAGS = ( DEFAULT => [qw(func1)], Both => [qw(func1 func2)]); sub func1 { return reverse @_ } sub func2 { return map{ uc }@_ } 1;
    For those emacs users, here's the simple script to generate the skeleton:
    (defun perl-new-module () "Generate a skeleton source for a traditional perl module." (interactive) (setq var (split-string (read-from-minibuffer "Enter module name (eg. Web::Test): "nil nil nil nil nil nil) " ")) (setq name (car var)) (insert (format "package %s;\n\n" name)) (insert "use strict;\n\n") (insert "use Exporter qw(import);\n") (insert "our @ISA = qw(Exporter);\n") (insert "our @EXPORT_OK = qw();\n") (insert "our %EXPORT_TAGS = ();\n") (insert "our $VERSION = 1.00; \n\n") (insert "\n\n\n\n\n\n") (insert "1;") (insert "\n") (previous-line 6) (end-of-line) )
[reply]
[d/l]
[select]
      Quite some years have gone by since the inital post, just want to point out that "use vars" is now considered deprecated, instead, "our" is prefered.

      Some people prefer to use our rather than use vars (I'm one of them) - but the latter is not deprecated. Both do slightly different things and many people still prefer to use vars.

[reply]
[d/l]
[select]
Re: Simple Module Tutorial
by twotone (Sexton) on Oct 14, 2007 at 05:06 UTC

    Great summary of module basics!

    Here's a little code I came up with to add my module location to @INC (in a cgi environment) by dynamically determining the document root for the script. It works on the remote apache server and when testing locally in windows. It might be of some interest:

    BEGIN { # get doc root from %ENV # implicitly declare file root path if %ENV not fount my $doc_root = $ENV{DOCUMENT_ROOT} || 'C:/Users/User/Documents/website/sites/mysite'; # change \ to / $doc_root =~ s/\\/\//g; # add module folder location $doc_root .= "/cgi-bin/cms/"; # add module location to @INC push(@INC,$doc_root); }
[reply]
[d/l]
      This tutorial is great. The only problem is, that I get the following result, if I comment out all the cases:

      !rekcaH~lreP~rehtonA~tsuJ
      JUST~ANOTHER~PERL~HACKER!
      !rekcaH~lreP~rehtonA~tsuJ
      JUST~ANOTHER~PERL~HACKER!
      !rekcaH~lreP~rehtonA~tsuJ
      JUST~ANOTHER~PERL~HACKER!
      !rekcaH~lreP~rehtonA~tsuJ
      JUST~ANOTHER~PERL~HACKER!

      Shouldn't there be some error messages or warnings?
[reply]
Re: Simple Module Tutorial
by chexmix (Friar) on Aug 12, 2008 at 13:24 UTC
    I like this post very much, but the following is opaque to me for some reason:

    "Case 3: The ':DEFAULT' tag *should* export &func1 so you might expect the error here to concern a missing &func2. In fact Perl complains about &func1. Hmm, what is going on here. The DEFAULT tag name is special and is automatically set in our modules %EXPORT_TAGS hash like this DEFAULT => \@EXPORT."

    I confess I still don't know what is going on here, and am wondering if someone can help me out.

    The words "is automatically set in our modules %EXPORT_TAGS hash like this DEFAULT => \@EXPORT" seem inaccurate to me, since when I look up at the code for MyModule.pm, I see the line

    %EXPORT_TAGS = ( DEFAULT => qw(&func1),

    and not the line

    %EXPORT_TAGS = ( DEFAULT => \@EXPORT,

    Is the OP saying that the line as is in the MyModule.pm code is incorrect, because the "special" nature of DEFAULT overrides it with something else?

    Thanks. I feel I am blanking on something obvious here, but just can't see it this rainy morning.

[reply]
      Is the OP saying that the line as is in the MyModule.pm code is incorrect, because the "special" nature of DEFAULT overrides it with something else?

      Yes. Exporter.pm wants :DEFAULT to match @EXPORT so the module is incorrect in trying to define its own meaning for :DEFAULT. Based on what you've quoted, it appears that Exporter.pm forces this issue, but the more important point is that you shouldn't set $EXPORT_TAGS{DEFAULT} yourself.

      - tye        

[reply]

Back to Tutorials


Login:
Password
remember me
What's my password?
Create A New User

Node Status
node history
Node Type: perltutorial [id://102347]
help
Community Ads
Chatterbox
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users
Others making s'mores by the fire in the courtyard of the Monastery: (11)
GrandFather
wfsp
atcroft
salva
herveus
Eyck
clinton
$self
vishi83
gnosti
eclpmb
As of 2009-11-21 09:42 GMT
Sections
The Monastery Gates
Seekers of Perl Wisdom
Meditations
PerlMonks Discussion
Categorized Q&A
Tutorials
Obfuscated Code
Perl Poetry
Cool Uses for Perl
Perl News
Information
PerlMonks FAQ
Guide to the Monastery
What's New at PerlMonks
Voting/Experience System
Tutorials
Reviews
Library
Perl FAQs
Other Info Sources
Find Nodes
Nodes You Wrote
Super Search
List Nodes By Users
Newest Nodes
Recently Active Threads
Selected Best Nodes
Best Nodes
Worst Nodes
Saints in our Book
Leftovers
The St. Larry Wall Shrine
Offering Plate
Awards
Craft
Snippets Section
Code Catacombs
Quests
Editor Requests
Buy PerlMonks Gear
PerlMonks Merchandise
Planet Perl
Perlsphere
Use Perl
Perl.com
Perl 5 Wiki
Perl Jobs
Perl Mongers
Perl Directory
Perl documentation
CPAN
Random Node
Voting Booth

Future historians will find that the material characteristic of the current era is...

Aluminium
Plastic
Oil
Water
Carbon dioxide
Copper
Iron
Silicon
Salt
Uranium
Hydrogen
Other

Results (729 votes), past polls