tags:

views:

305

answers:

3

I have two different versions of a Perl module. Currently, the crucial script uses the version of the module specified by an environment variable and the system relied on different tasks being run by different users. The user's environment would determine which version of the Perl module was used.

Now I would like to change this to the version being specified inside the Perl script, i.e. depending on the options passed. Unfortunately, code like this:

if ($new){ use lib "newdir"; }
else{ use lib "olddir"; }
use module;

doesn't work. Perl simply appends newdir and then olddir to @INC and then runs the script.

How do I dynamically specify which module to use?

+14  A: 

You need to use a BEGIN{} block so your if-else code will be run at compile-time:

BEGIN {
    if ($new) { unshift @INC, "newdir"; }
    else {      unshift @INC, "olddir"; }
}
use module;

You can also set the PERL5LIB environment variable so you wouldn't have to do this kind of configuration in the script.

mobrule
Your *weird* bracketing style has left you with an unclosed block. (Now, to start a bracketing war!)
Axeman
Eek. Thanks Axeman.
mobrule
Also worth mentioning is that "use lib" and manipulating @INC directly are not always equivalent operations. See the docs for more details.
jrockway
+10  A: 

There is an only pragma on CPAN that makes installing and then using multiple versions of the same module easy.

ysth
+2  A: 

If you would rather have your logic happen at runtime (for example if the $new variable is produced in some more complicated way that you don't want to run in a BEGIN block) you can use require() load the module at runtime.

The important thing to remember is that

use Module;
use ModuleWithExports qw(export1 export2);

Is the same as

BEGIN { require Module; Module->import() }
BEGIN {
    require ModuleWithExports;
    ModuleWithExports->import('export1', 'export2');
}

This means that to have your code run at runtime you can simply have:

if ($new) {
    unshift @INC, "newdir";
}
else {
    unshift @INC, "olddir";
}
require module;
module->import(); # if necessary

An alternative to using require() is to use the Module::Load module from CPAN.

Kaoru