tags:

views:

138

answers:

5

I am maintaining several Perl scripts that all have similar code blocks for different functions. Each time a code block is updated, I have to go through each script and manually make the change.

Is there a way to encapsulate the common functions into their own scripts and call them?

+12  A: 

Put the common functionality in a module. See perldoc perlmod for details.

moonshadow
Is there any way to do this without modules? I am not very good at perl and I was hoping there was a solution more like javascript-ish.
Charlie Brown
You can just make libraries. Again, we cover all of that in my book. :)
brian d foy
+2  A: 

About a third of Intermediate Perl is devoted to just this topic.

brian d foy
This strikes me as a comment, not an answer.
Telemachus
It strikes me as an answer as much as linking to a module or doc page is an answer.
brian d foy
@brian: yup, those are pretty much comments too. (If you were referring to Sinan's answer, though, I would say that he at least has the one sentence bullet-point answer of "Put the common stuff in a module." You just say, "My book tells you how to do this." Your response is actually, now that I look at it, a comment on Sinan's answer.)
Telemachus
Well, that's your opinion, and my mine is mine. Telling people where to find the info they need is my answer, and I'm going to keep answering like that when I think it's appropriate.
brian d foy
A link to a book is also useful, but this is more on par with a sales pitch.
Charlie Brown
+6  A: 

There are other ways, but they all have severe issues. Modules are the way to go, and they don't have to be very complicated. Here is a basic template:

package Mod;

use strict;
use warnings;

use Exporter 'import';

#list of functions/package variables to automatically export
our @EXPORT = qw(
    always_exported   
); 

#list of functions/package variables to export on request
our @EXPORT_OK = qw(
    exported_on_request
    also_exported_on_request
);

sub always_exported { print "Hi\n" }

sub exported_on_request { print "Hello\n" }

sub also_exported_on_request { print "hello world\n" }

1; #this 1; is required, see perldoc perlmod for details

Create a directory like /home/user/perllib. Put that code in a file named Mod.pm in that directory. You can use the module like this:

#!/usr/bin/perl

use strict;
use warnings;

#this line tells Perl where your custom modules are
use lib '/home/user/perllib';

use Mod qw/exported_on_request/;

always_exported();
exported_on_request();

Of course, you can name the file anything you want. It is good form to name the package the same as file. If you want to have :: in the name of the package (like File::Find) you will need to create subdirectories in /home/user/perllib. Each :: is equivalent to a /, so My::Neat::Module would go in the file /home/user/perllib/My/Neat/Module.pm. You can read more about modules in perldoc perlmod and more about Exporter in perldoc Exporter

Chas. Owens
Thanks, that is more clear than what I have been finding on the web, although I don't understand all the exporter stuff, I understand how to use it from your example.
Charlie Brown
A: 

Using a module is the most robust way, and learning how to use modules would be helpful.

Less efficient is the do function. Extract your code to a separate file, say "mysub.pl", and

do 'mysub.pl';

This will read and then eval the contents of the file.

glenn jackman
A: 

You can use the

require "some_lib_file.pl";

where you would put all your common functions and call them from other scripts which would contain the line above.

For example:

146$ cat tools.pl
# this is a common function we are going to call from other scripts
sub util()
{
    my $v = shift;
    return "$v\n";
}
1; # note this 1; the 'required' script needs to end with a true value

147$ cat test.pl
#!/bin/perl5.8 -w
require 'tools.pl';
print "starting $0\n";
print util("asdfasfdas");
exit(0);

148$ cat test2.pl
#!/bin/perl5.8 -w
require "tools.pl";
print "starting $0\n";
print util(1);
exit(0);

Then executing test.pl and test2.pl will yield the following results:

149$ test.pl
starting test.pl
asdfasfdas

150$ test2.pl
starting test2.pl
1
kirillka