John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

Suppose you want to grab a different version of just one function. Say, you've updated code and now want to call a newer thing, but have not updated the entire file yet.

use Module v1.0 qw/foo bar/; use Module v2.0 qw/baz/; # was not present in 1.0
That looks easy enough, and should work just fine. But, recall the handling of direct module calls, as opposed to calling through the imported hard link. If you write Module::foo it will decide at run-time that it must mean foo v1.0 based on the caller.

So, what happens if you call Module::zippo, something that was not directly imported also? Should that assume v1.0 or v2.0?

Musings:

However, I'd prefer to avoid the problem and not have the issue come up. E.g. some way to spot-import by version without making the user wonder what happens to the caller's "in use" setting.

For example, use a general syntax for renaming the import and specifying which version you want, and not re-specify a indirect version argument:

use Module v1.0 qw/foo bar/; use Module --rename => [\&baz, 'baz', v2.0];
Any ideas?

—John

Replies are listed 'Best First'.
Re: How should this work ? (design of Exporter::VA)
by traveler (Parson) on Dec 18, 2002 at 17:38 UTC
    Another approach would be to say, "I want to import only baz from v2.0. Everything else comes from 1.0" I'd do this with:
    use Module v1.0 qw/foo bar/; use Module v1.2 only qw/baz/;
    Of course, you could use -only or something similar. Then this would follow your "use the last" rule allowing:
    use Module v1.0 qw/foo bar/; use Module v1.2 only qw/baz/; use Module v1.7 gw/bam/;
    to mean "use bam from 1.7, baz from 1.2, foo and bar from 1.0. If the user asks for some thing explicitly try 1.7 first then 1.0."

    Just my USD(1.0/50), --traveler

      I like that. I was thinking of a "suppliment" keyword or somesuch that would be for subsequent invokations, but I like the semantics of "only". It would suppress setting up the direct-call autoload hooks, or prevent conflict if used subsequently.

      The import pragma switches are double-dashed. If you don't define them, they are inherited from Exporter::VA to control the export process itself. So I'd say use Module v1.2 qw/ --only baz /;.

      Looking at tye's reply, what would you name a switch that does the opposite, that is, enables the AUTOLOAD hook to allow direct calls to the module to be versioned?

      —John

        what would you name a switch that does the opposite, that is, enables the AUTOLOAD hook to allow direct calls to the module to be versioned?

        I had a bit of trouble parsing this. Do you mean setting a default version for calls to functions that aren't explicitly exported? If that's what you mean, I wouldn't do it. I look at the versions in reverse order of being used.

        If I'm not understanding, could you give an example?

        --traveler

(tye)Re: How should this work ? (design of Exporter::VA)
by tye (Sage) on Dec 18, 2002 at 17:52 UTC

    Perhaps the most robust approach would be to make it illegal by default and provide a method to make it explicit which one you want to be default. But I'd lean toward using    use Module v1.0 (); to set the explicit default. And if I did that then I'd probably opt for the simplified implementation and just use the last version number specified.

    And won't you run into modules that need to know the module version number of the desired behavior when some of their subroutines are called? I doubt such modules are likely to be fancier than the above.

            - tye
      I like the idea of not enabling the AUTOLOAD trapping to generate run-time version check redirection unless explicitly enabled.

      But, using () on use disables any call to import, so that's a complicating factor to using this syntax.

      Your last point: If I understand, suppose Module::Foo is not itself versioned via redirecting it to Foo_old or Foo_new. It's simply named Foo. It might contain an explicitly-coded run-time check to see if the client wants new behavior or old behavior. It can find out by calling a method on the blessed %EXPORT definition. If Foo calls _helper which then needs to know, it does it the same way.

      Ah, but that behavior is coded into the function directly and won't care if I call the imported link or the direct function, since they both work the same. So a switch to enable/disable the versioning is not going to mean anything to it. But there is no confusion, since the user asked for a specific version of Foo, regardless of what else he asked for. (It implies that I need per-function memory on this, rather than a single setting)

      —John