Perl6 - Subroutines and Modules

Lincoln Stein

Suggested Reading

Chapters 4 and 11 of Learning Perl, especially the section Using Simple Modules. Chapter 6 of Beginning Perl for Bioinformatics.

Lecture Notes

Subroutines

  1. Creating Subroutines
  2. Subroutine Arguments
  3. Subroutine Position in Scripts

Modules

  1. Using a Module
  2. Getting Module Documentation
  3. Installing Modules
  4. Where are Modules Installed?
  5. The Anatomy of a Module
  6. Exporting Variables & Functions from Modules

Problem Set

  1. Write a subroutine to concatenate two strings of DNA.
  2. Write a subroutine to report the percentage of each nucleotide in DNA. You've seen the plus operator +. You will also want to use the divide operator / and the multiply operator *. Count the number of each nucleotide, divide by the total length of the DNA, then multiply by 100 to get the percentage. Your arguments should be the DNA and the nucleotide you want to report on. The int function can be used to discard digits after the decimal point, if needed.
  3. Using the CPAN web site, locate a module for verifying credit card numbers. Download and build it (don't try to install it, because you need root privileges to do this).
  4. Using the standard object-oriented Math::BigInt library, which allows you to store really big integers, write a script that will read in a 100+ digit integer and calculate its square root.
  5. (extra credit) Create a module that counts the number of times a restriction site appears in a nucleotide string. The exported function should be named count_sites() and should be called like this:
          $count = count_sites('name_of_site',$nucleotide_string);
    
          # for example
          $count = count_sites('ecoRI','GGGATTTGACCGGAATTCCGATCCCAAGGTTC');
          
    Hints: Use a parenthesized regular expression and assign the results of a string match to an array. Store the relationships between the name of a restriction site and its regular expression in a hash.

Subroutines

Subroutines are blocks of code that you can call in different places and contexts. Subroutines can take arguments, and return results.

Why is this useful? Because it lets you solve a problem once and then reuse your solution over and over again. For example, say you've written a chunk of code that normalizes a DNA sequence by removing unwanted characters. By turning it into a named subroutine, you can reuse this piece of code over and over again within the same program without cutting and pasting. Later, you'll be able to put this subroutine into a personal code library and reuse it among many scripts.

Subroutines also make scripts shorter and easier to understand.

Example: Cleansing a Sequence

Sequences that come out of GenBank are "contaminated" with line numbers and whitespace, like this:

        1 aagacacgga agtagctccg aacaggaaga ggacgaaaaa aataaccgtc cgcgacgccg
       61 agacaaaccg gacccgcaac caccatgaac agcaaaggcc aatatccaac acagccaacc
      121 taccctgtgc agcctcctgg gaatccagta taccctcaga ccttgcatct tcctcaggct
      181 ccaccctata ccgatgctcc acctgcctac tcagagctct atcgtccgag ctttgtgcac
      241 ccaggggctg ccacagtccc caccatgtca gccgcatttc ctggagcctc tctgtatctt
      301 cccatggccc agtctgtggc tgttgggcct ttaggttcca caatccccat ggcttattat
      361 ccagtcggtc ccatctatcc acctggctcc acagtgctgg tggaaggagg gtatgatgca
      421 ggtgccagat ttggagctgg ggctactgct ggcaacattc ctcctccacc tcctggatgc
      481 cctcccaatg ctgctcagct tgcagtcatg cagggagcca acgtcctcgt aactcagcgg
      541 aaggggaact tcttcatggg tggttcagat ggtggctaca ccatctggtg aggaaccaag
      601 gccacctttg tgccgggaaa gacatcacat accttcagca cttctcacaa tgtaactgct
      661 ttagtcatat taacctgaag ttgcagttta gacacatgtt gttggggtgt ctttctggtg
      721 cccaaacttt caggcacttt tcaaatttaa taaggaacca tgtaatggta gcagtacctc
      781 cctaaagcat tttgaggtag gggaggtatc cattcataaa atgaatgtgg gtgaagccgc
      841 cctaaggatt ttcctttaat ttctctggag taatactgta ccatactggt ctttgctttt
      901 agtaataaaa catcaaatta ggtttggagg gaactttgat cttcctaaga attaaagttg
      961 ccaaattatt ctgattggtc tttaatctcc tttaagtctt tgatatatat tactttataa
     1021 atggaacgca ttagttgtct gccttttcct ttccatccct tgccccaccc atcccatctc
     1081 caaccctagt c

You want to remove all this extraneous stuff and turn the sequence into a single long string:

aagacacggaagtagctccgaacaggaagaggacgaaaaaaataaccgtccgcgacgccgagacaaaccggacccgcaaccaccatgaac...

To do this, you've written several statements that lowercase the sequence, and remove whitespace. If the sequence contains unexpected characters after this, we die:

$sequence = lc $sequence;  # translate everything into lower case
$sequence =~ s/[\s\d]//g;  # remove whitespace and numbers
$sequence =~ m/^[gatcn]+$/ or die "Sequence contains invalid characters!";

We can turn this into a named subroutine with the following three steps:

  1. Turn it into a block:
          {
            $sequence = lc $sequence;  # translate everything into lower case
            $sequence =~ s/[\s\d]//g;  # remove whitespace and numbers
            $sequence =~ m/^[gatcn]+$/ or die "Sequence contains invalid characters!";
          }
  2. Label the block with sub subroutine_name:
          sub cleanup_sequence
          {
            $sequence = lc $sequence;  # translate everything into lower case
            $sequence =~ s/[\s\d]//g;  # remove whitespace and numbers
            $sequence =~ m/^[gatcn]+$/ or die "Sequence contains invalid characters!";
          }
  3. Add statements to read the subroutine argument(s) and return the subroutine result(s):
          sub cleanup_sequence
          {
            my ($sequence) = @_;
            $sequence = lc $sequence;  # translate everything into lower case
            $sequence =~ s/[\s\d]//g;  # remove whitespace and numbers
            $sequence =~ m/^[gatcn]+$/ or die "Sequence contains invalid characters!";
            return $sequence;
          }

cleanup_sequence() now acts like a built-in function. It takes a list of arguments (in this case only one, the original sequence) and returns a list of results (in this case, only one, the cleaned-up sequence):

my $seq;
while (my $seqline = <IN>) { # read sequence from a file
  my $clean   = cleanup_sequence($seqline);  # clean it up
  $seq       .= $clean;                      # add it to full sequence
}


Getting Data in and out of a Subroutine

When you invoke a subroutine, you pass it a list of arguments and receive a list of results:

my @results = my_subroutine('arg1','arg2','arg3');

You'll now see how subroutines can retrieve its arguments and return its results.

Getting the Subroutine Arguments

Within the subroutine, the arguments are passed to it in an automatic ("magic") array variable named @_. One common idiom is for the first statement in a subroutine to copy @_ into a list of named variables:

sub my_subroutine {
   my ($arg1,$arg2,$arg3) = @_;
   ...
}

Returning the Subroutine Results

To return a list of results from a subroutine to its caller, use the return operator. Usually you will call return at the very end of the subroutine, but you can call it earlier in special cases if you want to exit the subroutine earlier.

This subroutine will add a PCR primer sequence to the beginning and end of a DNA sequence and return the result.

sub add_linkers {
   my ($linker,$sequence) = @_;
   my $reverse_linker = $linker;
   $reverse_linker    =~ tr/gatcGATC/ctagCTAG/;  # reverse complement it
   my $result         = $linker . $sequence . $reverse_linker;
   return $result;
}

You can return a single value, a list, or nothing:

  return $single_value;  # scalar
  return ('a','long','list','of','items');  # list
  return @an_array;      # list contained in an array variable
  return;                # return empty list or undef, depending on context

Subroutine Anatomy

Anatomy of a Subroutine

Lastly, the age old question, Where do you put the subroutines in your script?. Usually the subroutine definitions go at the bottom of the script, following the last statement.

To visually separate the statements from the subroutine, you can add a comment line if you like.

  #!/usr/bin/perl
  use warnings;
  use strict;
  # comments describing what the script does
  # more comments, including author and script name

  my ($variables, $variables, @more_variables);   # declare some variables

  while (my $line = <IN>) {
     my @results = subroutine_1();
     my $result  = subroutine_2(\@results);
  }

  do_something_at_end_of_script;


  ### Subroutines ###

  sub subroutine_1 {
     my ($local1,$local2,$local3) = @_;
     do_something;
  }

  sub subroutine_2 {
     my ($local1,$local2,$local3) = @_;
     do_something;
  }


Modules

Using a Module

A module is a package of useful subroutines and variables that someone has put together. Modules extend the ability of Perl.

Example 1: The File::Basename Module

The File::Basename module is a standard module that is distributed with Perl. When you load the File::Basename module, you get two new functions, basename and dirname.

basename takes a long UNIX path name and returns the file name at the end. dirname takes a long UNIX path name and returns the directory part.

  
  #!/usr/bin/perl
  # file: basename.pl

  use warnings;
  use strict;
  use File::Basename;

  my $path = '/bush_home/bush1/lstein/C1829.fa';
  my $base = basename($path);
  my $dir  = dirname($path);

  print "The base is $base and the directory is $dir.\n";

The output of this program is:

The base is C1829.fa and the directory is /bush_home/bush1/lstein.

The use function loads up the module named File::Basename and imports the two functions. If you didn't use use, then the program would print an error:

Undefined subroutine &main::basename called at basename.pl line 8.

Example 2: The Env Module

The Env module is a standard module that provides access to the environment variables. When you load it, it imports a set of scalar variables corresponding to your environment.

#!/usr/bin/perl
# file env.pl

use warnings;
use strict;
use Env;

print "My home is $HOME\n";
print "My path is $PATH\n";
print "My username is $USER\n";

When this runs, the output is:

My home is /bush_home/bush1/lstein
My path is /net/bin:/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin:/bush_home/bush1/lstein/bin:.
My username is lstein


Finding out What Modules are Installed

Here are some tricks for finding out what modules are installed.

Preinstalled Modules

To find out what modules come with perl, look in Appendix A of Perl 5 Pocket Reference. From the command line, use the perldoc command from the UNIX shell. All the Perl documentation is available with this command:

% perldoc perlmodlib
PERLMODLIB(1)  User Contributed Perl Documentation  PERLMODLIB(1)



NAME
       perlmodlib - constructing new Perl modules and finding
       existing ones

DESCRIPTION
THE PERL MODULE LIBRARY
       Many modules are included the Perl distribution.  These
       are described below, and all end in .pm.  You may discover
...
       Standard Modules

       Standard, bundled modules are all expected to behave in a
       well-defined manner with respect to namespace pollution
       because they use the Exporter module.  See their own docu-
       mentation for details.

       AnyDBM_File Provide framework for multiple DBMs

       AutoLoader  Load subroutines only on demand

       AutoSplit   Split a package for autoloading

       B           The Perl Compiler
...

To learn more about a module, run perldoc with the module's name:

% perldoc File::Basename

NAME
       fileparse - split a pathname into pieces

       basename - extract just the filename from a path

       dirname - extract just the directory from a path

SYNOPSIS
           use File::Basename;

           ($name,$path,$suffix) = fileparse($fullname,@suffixlist)
           fileparse_set_fstype($os_string);
           $basename = basename($fullname,@suffixlist);
           $dirname = dirname($fullname);
...

Optional Modules that You May Have Installed

perldoc perllocal will list the names of locally installed modules.

% perldoc perllocal
       Thu Apr 27 16:01:31 2000: "Module" the DBI manpage


       o   "installed into: /usr/lib/perl5/site_perl"

       o   "LINKTYPE: dynamic"

       o   "VERSION: 1.13"

       o   "EXE_FILES: dbish dbiproxy"

       Thu Apr 27 16:01:41 2000: "Module" the Data::ShowTable
       manpage


       o   "installed into: /usr/lib/perl5/site_perl"

       o   "LINKTYPE: dynamic"

       o   "VERSION: 3.3"

       o   "EXE_FILES: showtable"

       Tue May 16 18:26:27 2000: "Module" the Image::Magick man-
       page
...

But often it's just easier to test directly using perl itself:

% perl -e 'use File::Basename;' %
If you get no error when you try to use the module, then the module is installed.


Installing Modules

You can find thousands of Perl Modules on CPAN, the Comprehensive Perl Archive Network:

http://www.cpan.org

Installing Modules Manually

Search for the module on CPAN using the keyword search. When you find it, download the .tar.gz module. Then install it like this:

% tar zxvf bioperl-1.6.1.tar.gz
bioperl-1.6.1/
bioperl-1.6.1/Bio/
bioperl-1.6.1/Bio/DB/
bioperl-1.6.1/Bio/DB/Ace.pm
bioperl-1.6.1/Bio/DB/GDB.pm
bioperl-1.6.1/Bio/DB/GenBank.pm
bioperl-1.6.1/Bio/DB/GenPept.pm
bioperl-1.6.1/Bio/DB/NCBIHelper.pm
bioperl-1.6.1/Bio/DB/RandomAccessI.pm
bioperl-1.6.1/Bio/DB/SeqI.pm
bioperl-1.6.1/Bio/DB/SwissProt.pm
bioperl-1.6.1/Bio/DB/UpdateableSeqI.pm
bioperl-1.6.1/Bio/DB/WebDBSeqI.pm
bioperl-1.6.1/Bio/AlignIO.pm

%  perl Makefile.PL
Generated sub tests. go make show_tests to see available subtests
...
Writing Makefile for Bio

% make
cp Bio/Tools/Genscan.pm blib/lib/Bio/Tools/Genscan.pm
cp Bio/Root/Err.pm blib/lib/Bio/Root/Err.pm
cp Bio/Annotation/Reference.pm blib/lib/Bio/Annotation/Reference.pm
cp bioback.pod blib/lib/bioback.pod
cp Bio/AlignIO/fasta.pm blib/lib/Bio/AlignIO/fasta.pm
cp Bio/Location/NarrowestCoordPolicy.pm blib/lib/Bio/Location/NarrowestCoordPolicy.pm
cp Bio/AlignIO/clustalw.pm blib/lib/Bio/AlignIO/clustalw.pm
cp Bio/Tools/Blast/Run/postclient.pl blib/lib/Bio/Tools/Blast/Run/postclient.pl
cp Bio/LiveSeq/Intron.pm blib/lib/Bio/LiveSeq/Intron.pm
...
Manifying blib/man3/Bio::LiveSeq::Exon.3
Manifying blib/man3/Bio::Location::CoordinatePolicyI.3
Manifying blib/man3/Bio::SeqFeature::Similarity.3

% make test
PERL_DL_NONLAZY=1 /net/bin/perl -Iblib/arch -Iblib/lib
 -I/net/lib/perl5/5.6.1/i686-linux -I/net/lib/perl5/5.6.1 -e 'use
 Test::Harness qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
t/AAChange..........ok                                                       
t/AAReverseMutate...ok                                                       
t/AlignIO...........ok                                                       
t/Allele............ok
...
t/WWW...............ok                                                       
All tests successful, 95 subtests skipped.
Files=60, Tests=1011, 35 wallclock secs (25.47 cusr +  1.60 csys = 27.07 CPU)

% make install
Installing /net/lib/perl5/site_perl/5.6.1/bioback.pod
Installing /net/lib/perl5/site_perl/5.6.1/biostart.pod
Installing /net/lib/perl5/site_perl/5.6.1/biodesign.pod
Installing /net/lib/perl5/site_perl/5.6.1/bptutorial.pl
...

Installing Modules Using the CPAN Shell

Perl has a CPAN module installer built into it. You run it like this:

% cpan

cpan shell -- CPAN exploration and modules installation (v1.59_54)
ReadLine support enabled

cpan>

From this shell, there are commands for searching for modules, downloading them, and installing them.

[The first time you run the CPAN shell, it will ask you a lot of configuration questions. Generally, you can just hit return to accept the defaults. The only trick comes when it asks you to select CPAN mirrors to download from. Choose any ones that are in your general area on the Internet and it will work fine.]

Here is an example of searching for the Text::Wrap program and installing it:

cpan> i /Wrap/
Going to read /bush_home/bush1/lstein/.cpan/sources/authors/01mailrc.txt.gz
CPAN: Compress::Zlib loaded ok
Going to read /bush_home/bush1/lstein/.cpan/sources/modules/02packages.details.txt.gz
  Database was generated on Tue, 16 Oct 2001 22:32:59 GMT
CPAN: HTTP::Date loaded ok
Going to read /bush_home/bush1/lstein/.cpan/sources/modules/03modlist.data.gz
Distribution    B/BI/BINKLEY/CGI-PrintWrapper-0.8.tar.gz
Distribution    C/CH/CHARDIN/MailQuoteWrap0.01.tgz
Distribution    C/CJ/CJM/Text-Wrapper-1.000.tar.gz
...
Module          Text::NWrap     (G/GA/GABOR/Text-Format0.52+NWrap0.11.tar.gz)
Module          Text::Quickwrap (Contact Author Ivan  Panchenko )
Module          Text::Wrap      (M/MU/MUIR/modules/Text-Tabs+Wrap-2001.0929.tar.gz)
Module          Text::Wrap::Hyphenate (Contact Author Mark-Jason Dominus )
Module          Text::WrapProp  (J/JB/JBRIGGS/Text-WrapProp-0.03.tar.gz)
Module          Text::Wrapper   (C/CJ/CJM/Text-Wrapper-1.000.tar.gz)
Module          XML::XSLT::Wrapper (M/MU/MULL/XML-XSLT-Wrapper-0.32.tar.gz)
41 items found

cpan> install Text::Wrap
Running install for module Text::Wrap
Running make for M/MU/MUIR/modules/Text-Tabs+Wrap-2001.0929.tar.gz
CPAN: LWP::UserAgent loaded ok
Fetching with LWP:
  ftp://archive.progeny.com/CPAN/authors/id/M/MU/MUIR/modules/Text-Tabs+Wrap-2001.0929.tar.gz
CPAN: MD5 loaded ok
Fetching with LWP:
  ftp://archive.progeny.com/CPAN/authors/id/M/MU/MUIR/modules/CHECKSUMS
Checksum for /bush_home/bush1/lstein/.cpan/sources/authors/id/M/MU/MUIR/modules/Text-Tabs+Wrap-2001.0929.tar.gz ok
Scanning cache /bush_home/bush1/lstein/.cpan/build for sizes
Text-Tabs+Wrap-2001.0929/
Text-Tabs+Wrap-2001.0929/MANIFEST
Text-Tabs+Wrap-2001.0929/CHANGELOG
Text-Tabs+Wrap-2001.0929/Makefile.PL
Text-Tabs+Wrap-2001.0929/t/
Text-Tabs+Wrap-2001.0929/t/fill.t
Text-Tabs+Wrap-2001.0929/t/tabs.t
Text-Tabs+Wrap-2001.0929/t/wrap.t
Text-Tabs+Wrap-2001.0929/README
Text-Tabs+Wrap-2001.0929/lib/
Text-Tabs+Wrap-2001.0929/lib/Text/
Text-Tabs+Wrap-2001.0929/lib/Text/Wrap.pm
Text-Tabs+Wrap-2001.0929/lib/Text/Tabs.pm

  CPAN.pm: Going to build M/MU/MUIR/modules/Text-Tabs+Wrap-2001.0929.tar.gz

Checking if your kit is complete...
Looks good
Writing Makefile for Text
cp lib/Text/Wrap.pm blib/lib/Text/Wrap.pm
cp lib/Text/Tabs.pm blib/lib/Text/Tabs.pm
Manifying blib/man3/Text::Wrap.3
Manifying blib/man3/Text::Tabs.3
  /usr/bin/make  -- OK
Running make test
PERL_DL_NONLAZY=1 /net/bin/perl -Iblib/arch -Iblib/lib
-I/net/lib/perl5/5.6.1/i686-linux -I/net/lib/perl5/5.6.1 -e 'use
Test::Harness qw(&runtests $verbose); $verbose=0; runtests @ARGV;' t/*.t
t/fill..............ok
t/tabs..............ok
t/wrap..............ok
All tests successful.
Files=3, Tests=37,  0 wallclock secs ( 0.20 cusr +  0.00 csys =  0.20 CPU)
  /usr/bin/make test -- OK
Running make install
Installing /net/lib/perl5/5.6.1/Text/Wrap.pm
Installing /net/man/man3/Text::Wrap.3
Installing /net/man/man3/Text::Tabs.3
Writing /net/lib/perl5/5.6.1/i686-linux/auto/Text/.packlist
Appending installation info to /net/lib/perl5/5.6.1/i686-linux/perllocal.pod
  /usr/bin/make install UNINST=1 -- OK

cpan> quit
Lockfile removed.

Where are Modules Installed?

Module files end with the extension .pm. If the module name is a simple one, like Env, then Perl will look for a file named Env.pm. If the module name is separated by :: sections, Perl will treat the :: characters like directories. So it will look for the module File::Basename in the file File/Basename.pm

Perl searches for module files in a set of directories specified by the Perl library path. This is set when Perl is first installed. You can find out what directories Perl will search for modules in by issuing perl -V from the command line:

 % perl -V
 Summary of my perl5 (revision 5.0 version 6 subversion 1) configuration:
  Platform:
    osname=linux, osvers=2.4.2-2smp, archname=i686-linux
 ...
  Compiled at Oct 11 2001 11:08:37
  @INC:
    /usr/lib/perl5/5.6.1/i686-linux
    /usr/lib/perl5/5.6.1
    /usr/lib/perl5/site_perl/5.6.1/i686-linux
    /usr/lib/perl5/site_perl/5.6.1
    /usr/lib/perl5/site_perl
    .

You can modify this path to search in other locations by placing the use lib command somewhere at the top of your script:

  #!/usr/bin/perl

  use warnings;
  use strict;
  use lib '/home/lstein/lib';
  use MyModule;
  ...

This tells Perl to look in /home/lstein/lib for the module MyModule before it looks in the usual places. Now you can install module files in this directory and Perl will find them.

Sometimes you really need to know where on your system a module is installed. Perldoc to the rescue again -- use the -l command-line option:

% perldoc -l File::Basename
/System/Library/Perl/5.8.8/File/Basename.pm


The Anatomy of a Module File

Here is a very simple module file named "MySequence.pm":

package MySequence;
#file: MySequence.pm

use warnings;
use strict;
our $EcoRI = 'ggatcc';

sub reverseq {
  my $sequence = shift;
  $sequence = reverse $sequence;
  $sequence =~ tr/gatcGATC/ctagCTAG/;
  return $sequence;
}

sub seqlen {
  my $sequence = shift;
  $sequence =~ s/[^gatcnGATCN]//g;
  return length $sequence;
}

1;

A module begins with the keyword package and ends with "1;". package gives the module a name, and the 1; is a true value that tells Perl that the module compiled completely without crashing.

The our keyword declares a variable to be global to the module. It is similar to my, but the variable can be shared with other programs and modules ("my" variables cannot be shared outside the current file, subroutine or block). This will let us use the variable in other programs that depend on this module.

To install this module, just put it in the Perl module path somewhere, or in the current directory.

Using the MySequence.pm Module

Using this module is very simple:
  #!/usr/bin/perl
  #file: sequence.pl

  use warnings;
  use strict;
  use MySequence;

  my $sequence = 'gattccggatttccaaagggttcccaatttggg';
  my $complement = MySequence::reverseq($sequence);

  print "original   = $sequence\n";
  print "complement = $complement\n";

% sequence.pl
original   = gattccggatttccaaagggttcccaatttggg
complement = cccaaattgggaaccctttggaaatccggaatc

Unless you explicitly export variables or functions, the calling function must explicitly qualify each MySequence function by using the notation:

MySequence::function_name

For a non-exported variable, the notation looks like this:

$MySequence::EcoRI

Exporting Variables and Functions from Modules

To make your module export variables and/or functions like a "real" module, use the Exporter module.

package MySequence;
#file: MySequence.pm

use warnings;
use strict;
use base 'Exporter';

our @EXPORT    = qw(reverseq seqlen);
our @EXPORT_OK = qw($EcoRI);

our $EcoRI = 'ggatcc';

sub reverseq {
  my $sequence = shift;
  $sequence = reverse $sequence;
  $sequence =~ tr/gatcGATC/ctagCTAG/;
  return $sequence;
}

sub seqlen {
  my $sequence = shift;
  $sequence =~ s/[^gatcnGATCN]//g;
  return length $sequence;
}

1;

The use base 'Exporter' line tells Perl that this module is a type of "Exporter" module. As we will see later, this is a way for modules to inherit properties from other modules. The Exporter module (standard in Perl) knows how to export variables and functions.

The our @EXPORT = qw(reverseq seqlen) line tells Perl to export the functions reverseq and seqlen automatically. The our @EXPORT_OK = qw($EcoRI) tells Perl that it is OK for the user to import the $EcoRI variable, but not to export it automatically.

The qw() notation is telling Perl to create a list separated by spaces. These lines are equivalent to the slightly uglier:

our @EXPORT    = ('reverseq','seqlen');

Using the Better MySequence.pm Module

Now the module exports its reverseq and seqlen functions automatically:
  #!/usr/bin/perl
  #file: sequence2.pl

  use warnings;
  use strict;
  use MySequence;

  my $sequence = 'gattccggatttccaaagggttcccaatttggg';
  my $complement = reverseq($sequence);

  print "original   = $sequence\n";
  print "complement = $complement\n";

The calling program can also get at the value of the $EcoRI variable, but he has to ask for it explicitly:
  #!/usr/bin/perl
  #file: sequence3.pl

  use warnings;
  use strict;
  use MySequence;

  my $sequence = 'gattccggatttccaaagggttcccaatttggg';
  my $complement = reverseq($sequence);

  print "original   = $sequence\n";
  print "complement = $complement\n";

  if ($complement =~ /$EcoRI/) {
    print "Contains an EcoRI site.\n";
  } else {
    print "Doesn't contain an EcoRI site.\n";
  }


POD - Documenting your code

We've used the # sign to comment out lines in our programs, and they're a good form of documenting our code. But comment are only visible when we look at the code, not when we run the program.

But there are other ways to document your code, and the one most commonly used in Perl is POD. When you add POD to your code, then you can produce your very own man page for your program.