newest_newbie has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I want to have a Module with two different versions (say 1.0 and 2.0). The Module should behave differently when I use
use Module 1.0;
and
use Module 2.0;
How can I achieve this. Should I have two Module.pm files? or should I have two sets of subroutines in the same file? I tried something like this, DID NOT WORK, it always picked the last defined subroutine.
package Module; our ($VERSION, @EXPORT, @ISA); use Exporter; @ISA=qw#Exporter#; $VERSION = q#1.0#; sub routine1 { print "This is version: $VERSION\n"; } $VERSION = q#2.0#; sub routine1 { print "This is version: $VERSION\n"; } 1;
Thanks in advance!!

Replies are listed 'Best First'.
Re: Multiple versions of a module
by Fletch (Bishop) on Mar 16, 2007 at 18:48 UTC

    Not that it's necessarily a good idea, but you could make the top-level package a wrapper with a custom import subroutine. That sub would examine the version argument passed and itself require Module::Version1 or Module::Version2 and then arrange for the appropriate exporting to be done from those modules back into the caller's namespace.

Re: Multiple versions of a module
by Joost (Canon) on Mar 16, 2007 at 19:00 UTC
    You can use a custom import() routine (see use) to change the API of a module based on the argument list to use, but that would break the possibility of using different APIs in different sections of the program or at least it would require you to bind the API version to the caller's package which would be messy.

    If you're going to base all your functionality on objects, you could also base the API version on some argument to the object's constructor.

    In any case, I wouldn't recommend doing either. If the changes are minor, you could probably get away with adding new versions of routines under another name. If the changes are significant, I'd probably just create a new module, possibly incorporating the main version number in the module name, i.e. use Module2; vs use Module;

Re: Multiple versions of a module
by gam3 (Curate) on Mar 16, 2007 at 20:27 UTC
    You can use the VERSION method.
    package Module; use Data::Dumper; sub VERSION { my $class = shift; my $version = shift; require(sprintf("%s_%d.pm", $class, $version)); push @ISA, $class . '_' . $version; 1; } 1;
    If you want to use 2.1 you will need to convert the numbers into something like 2_1, as Module_2.1 is not a valid Module name.
    -- gam3
    A picture is worth a thousand words, but takes 200K.
Re: Multiple versions of a module
by shigetsu (Hermit) on Mar 16, 2007 at 21:12 UTC
Re: Multiple versions of a module
by ferreira (Chaplain) on Mar 17, 2007 at 18:49 UTC

    Usually using at the same time two versions of a module cannot be done because one version (the first found via the @INC path) would override the other(s). Even if you tried to require them via file paths instead of module names, they would fight for the same namespace with unpleasant consequences or with the last one to be loaded winning the game (if you're lucky).

    But you may achieve this effect by using the CPAN module only.

    use only Module 1.0; # or use only Module 2.0;
    according to what you want in a certain piece of code. But... current only has a bunch of issues (as may be seen from the tests of the current distribution: 14 PASS x 19 FAIL x 1 NA) and demands a change in the installation mantra:
    perl Makefile.PL make make test perl -Monly=install # substitute for 'make install'

    So it may demand some effort to make it work right.

    On the other hand, if what you're trying to achieve is just a module that has two faces according to how it is used, you may give up the idea of using the version to stand for this difference and use instead some argument to the import function. You'll see this in many modules via special import tags like :strict, which triggers a certain operating mode in the module. One such example is the strict mode in the XML::Simple module:

    use XML::Simple qw(:strict);

    As always, there are a bunch of issues/drawbacks with this approach, like not being able to use different modes in the same application running (even in different parts of the code). This restriction may be due to the implementation code which makes use of package variables (as it is common). Sometimes, you'll regret those operation modes of the module are not only operation modes of an object which can be more flexibly configured and handled.