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

Fellow monks,

I have an interesting dillema. Due to forces outside of my control, I have to work with existing code which has something like:

use myPackage; myPackage::foo(); myPackage::bar();

The problem is that in my environment, I cannot have the obsolete myPackage module because it has been replaced with myNewPackage module. The nice thing is that this myNewPackage has almost a one to one mapping of function names (and their functionality). So, I was hoping to write my own dummy myPackage which would actually do something like:
package myPackage; use strict; use myNewPackage; # magically convert myNewPackage::* to myPackage()::* # except for one function where myNewPackage::bar() needs to actually +provide myPackage::old_bas()
it seems like something like this should be possible, but I cannot think of an easy way to do it short of actually going through every function and creating an explicit mapping like (pseudocode):
sub myPackage::a { return myNewPackage::a(@_); } sub myPackage::b { return myNewPackage::b(@_); } sub myPackage::old_bas { return myNewPackage::bar(@_); }
Does anyone have any good ideas for how to deal with this?

thanks as always!

Replies are listed 'Best First'.
Re: creating a wrapper module for bacward compatibility
by LanX (Saint) on Apr 09, 2010 at 13:22 UTC
    > Does anyone have any good ideas for how to deal with this?

    yes you can use Autoloading to dynamically catch every call to a an old sub and redirect it.

    you can even automatically create these new subs, such that the next call will be faster.

    if you just want a static mapping you can use something like

    *myNewPackage::b=*myPackage::b

    in a loop over a hash defining the mappings.

    That are untested ideas, hope you can elaborate it yourself. :)

    Cheers Rolf

    UPDATE: link repaired.

Re: creating a wrapper module for backward compatibility
by moritz (Cardinal) on Apr 09, 2010 at 13:21 UTC
    Seems like AUTOLOAD should do the trick for you.
Re: creating a wrapper module for bacward compatibility
by RatKing (Acolyte) on Apr 09, 2010 at 13:41 UTC

    Would one not be able to do something like this:

    package mypackage; use base mynewpackage;

    This should make mypackage have all the functions that mynewpackage has, at least this is what I would try...

    I have no idea about performance though but it might be interesting to see if this can out perform Autoload I think it should be able to.

      This should make mypackage have all the functions that mynewpackage has, at least this is what I would try.
      Are you sure? According to its manual page, base sets up an ISA relationship. Which means that mypackage inherits the methods from mynewpackage. Which is fine if the subs are called as methods, but the OP has to deal with myPackage::foo() calls. He needs mypackage to import from mynewpackage instead.
      the sub-names are not always identical (old_bas->bar) and he will sometimes need more flexibility.

      For instance for extra logic or even for extra error handling and testing to stabilize this "bridge".

      Overall this is not trivila and should be handled with care and foresight...

      Cheers Rolf

Re: creating a wrapper module for bacward compatibility
by doug (Pilgrim) on Apr 09, 2010 at 17:59 UTC

    Personally, I think explicitly mapping old to new like this is a good thing. I'm a geek, so I'd write something that did it for me. This way you have a single place to look up all the translations, and if you need to tweak one of the parameters, then you can do so easily.

    A few years ago, I would have done it via AUTOLOAD. That approach is only going to work when you have known rules for mapping the old way to the new way. Any oddballs would require coding them up explicitly and using AUTOLOAD for the default case. Now days I'd prefer to spell everything out and not worry about any of the corner cases. This is the triumph of true laziness over false laziness.

    - doug

    BTW: To get the list of things to be translated, write a little script that has  use MyPackage; and then look through the MyPackage symbol table. Run them through a loop (map?) and spit out the default translators. I'd give you the syntax for doing this, but I know that I never get it right the first time or two. I don't have the time to get it right, and I don't want to send you off on a syntactical wild goose chase.