|Problems? Is your data what you think it is?|
Comment onby gods
|on Feb 11, 2000 at 00:06 UTC||Need Help??|
Some simple languages, like PHP, offer an include() to include a file literally. Perl does not. Then how can you still load code from other files?
There are many ways to do this in Perl, but there is no easy way to get close to what most people expect of an include(). People who want to include files usually come from simpler languages, or have no programming experience at all. The hardest thing they will have to learn is that you should not want to include a file.
That may sound harsh, but it's a Perl reality. In Perl, we don't include or link libraries and code reuse isn't usually done by copying and pasting. Instead, Perl programmers use modules. The keywords use and require are meant for use with modules. Only in the simplest of situations you can get away with abusing require as if it were some kind of include(), but it's easy to get bitten by how it works: it only loads any given file once.
Creating a module
What is a module, anyway? perlmod defines it as: just a set of related functions in a library file, i.e., a Perl package with the same name as the file.
Creating a module is EASY, but it is a little more work than just creating a file with code in it. First, you need to think of a module name. This is the basis for both the filename and the package name, and these have to be synchronised for some features to work. For project specific modules, I always create a new top-level namespace with the name of the project. For example, NameOfTheProject/SomeModule.pm is a good filename (in real life, use something a little more meaningful). The corresponding package is NameOfTheProject::SomeModule. Use CamelCaps like this, because everyone else does too.
The file must be in a directory that is listed in @INC. To find out what your @INC is, run perl -V. The current working directory (listed as its symbolic name . (a single dot)) should be listed. To begin with, putting the module in the script's directory is a good idea. It is the easiest way to keep things organized. If you want to put the module somewhere else, you will have to update @INC, so that perl knows where to find it. An easy way to do get code like this in the main script:
What goes in the module itself doesn't require much explanation. I'll just give a complete example of a simple NameOfTheProject::SomeModule:
Just list all the subs as you usually would, put a package statement at the top and a true value at the bottom (1 will suffice). Obviously, use strict is a good idea. You should never code a module that does not have this. Beware: A use strict; statement in the main script has no effect on the module.
A module runs only once. That means that for code to be reusable, it must be in a sub. In fact, it's considered very bad style to do anything (except declaring and initializing some variables) in the module's main code. Just don't do that.
You can now load the module and use its sub, simply by doing:
Then, when useing the module, you can request that some_function be imported to your namespace with:
To have it exported automatically, use @EXPORT instead of @EXPORT_OK. This will eventually bite you if the function names are generic. For example, many people get bitten by LWP::Simple's get function. It is not unlikely that you already have one.
There are more ways to export functions. I of course prefer to use my own module Exporter::Tidy. Not only because it's smaller and often faster, but mostly because it lets the user of a module define a prefix to avoid clashes. Read its documentation for instructions.
For the export/import mechanism, it is very important that the filename, the package name and the name used with use are equal. This is case sensitive. (Ever wondered why under Windows, use Strict; doesn't enable strict, but also doesn't emit any warning or error message? It has everything to do with the case insensitive filesystem that Windows uses.)
Stubbornly still wanting to include
Sometimes, a module just isn't logical. For example, when you want to use an external configuration file. (Many beginners and people who post code online put configuration in the script itself for ease of use, but this makes upgrading the script harder.) There are many configuration file reader modules you can use, but why use one of those if you can just use bare Perl?
This is where do comes in. What do does is very close to what an include would do, but with a very annoying exception: the new file gets its own lexical scope. In other words: a variable declared with my is not accessible externally. This follows all logical rules attached to lexical variables, but can be very annoying. Fortunately, this does not have to be a problem. do returns whatever the included script returned, and if you make that script just the contents of a hash, here's my favourite way to offer configurability:
(The last , is optional, but it's included to make adding a line easier.)
Error checking is left as an excercise.
Because we used only the return value of the script, and never even touched a variable in config.pl, the inaccessibility of lexical variables is no longer a problem. Besides that, the code looks very clean and we have a very powerful config file format that automatically supports comments and all kinds of useful functions. How about interval => 24 * 60 * 60, for self-documentation? :)
Still not good enough
There is a way to get an include() the way other languages have it. This is a very ugly hack that uses an internal exception made for Perl's debugger, and is possibly not future proof. As said before, you should not want to include a file. Still, because it is possible, I feel I have to tell you how. Just don't actually use it.
If you read the documentation for eval (which you of course should (don't use an operator without having read its documentation first)), you see that if it is called from within the DB package, it is executed in the caller's scope. This means that lexical values are made visible and the file behaves as a code block.
Here is an example to get an include() function that actually works the way most people expect:
Documentation for the #line directive is in perlsyn.
To test this new module, save it as Acme/Include.pm and create:
and then run perl foo.pl.
This example Acme::Include does not have any error checking. In practice, you will want to check $@ somewhere (but you also want to retain the value returned by the included file, and context to propagate properly. Good luck!).
I wrote this tutorial to have an answer ready for the nth time someone in EFnet's #perlhelp asks why require works only once, or asks how to really include a file. Explaining the same thing over and over gets annoying over time. This is not a good guide to writing modules. For that, read chapter 10 of Beginning Perl and perlmod and perlnewmod. Of course, good code always comes with good documentation; so learn POD in 5 minutes.
One last thing
If you name your module Test, don't be surprised if it doesn't work. The current working directory comes last in @INC, so the Test module that is in the Perl distribution is probably loaded instead. This bites me at least once per year, this time while writing this tutorial :).