in reply to BEGIN and compile-time
That way, your script works regardless of whether the module is moved about on the filesystem or your script is used on another machine.use Module VERSION # e.g. use Foo::Bar 5.01; # <- just v5.01 please, TYVM # or better still eval "use Foo::Bar 5.01" or do { use Foo::Bar } # fallback incase the 'required' version isnt available
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: BEGIN and compile-time
by ikegami (Patriarch) on Nov 09, 2006 at 05:58 UTC | |
That doesn't do what you expect. The second use Foo::Bar gets executed first, and it gets executed unconditionally. Why would you want to fallback to the same module anyway? That's the same as not putting a version in the first place! If you wanted to fallback to a different module, the following will do:
VERSION is documented in UNIVERSAL. | [reply] [d/l] [select] |
by Firefly258 (Beadle) on Nov 09, 2006 at 11:58 UTC | |
Why fallback to the same module?? Well, maybe we do need it but ideally we'd like to take control and load the one version of it identified by a supplied version number but if the module at that version isn't available, prepare the script for the standard version and continue, something along the lines of OP's wants. So, as has already been examined, "use lib '../'; use Foo::Bar;" seems to have worked simply and elegantly.. but "use lib" places entries at the beginning of @INC and what if non-standard versions of ../strict.pm or ../warnings.pm existed? The user might inadvertently load these modules (OUCH!!) rather than the ones in the original @INC. Placing entries at the beginning of @INC is a bad idea, the risk of polluting the package with bogus code as a result of namespace clashes is real. Placing entries at the end of @INC means that modules if found in the original @INC take precendence and are loaded instead of the ones you want loading. The chances are of such a case are slim but entirely possible especially if the user isn't aware of the perl module namespace. Even otherwise, the user might be patching/updating the an already existant module and can ensure the testing release is loaded by using it's $VERSION (wherever the new .pm is located via @INC). Placing entries at the end of @INC is generally safer. As an added benefit, using the $Foo::Bar::VERSION to validate loading Foo::Bar also ensures that your code is guaranteed to run under Foo::Bar, alternate versions of the module might break something. So if the OP wanted to load a non-standard Foo::Bar (let's assume v5.00) instead of a standard Foo::Bar (v5.01) and provided the version numbers reported by the 2 modules were different (they really ought to be) ...
| [reply] [d/l] [select] |
by ikegami (Patriarch) on Nov 09, 2006 at 15:38 UTC | |
I'm not sure why you are advocating adding to the back of @INC or how it relates to the thread, but adding to the front of @INC is definitely the way to go. There are two reasons to add to @INC: So placing it at the front is claearly preferable. There are no reasons to place it at the back.
You're inventing problems. If .. was added to the end of @INC, your non-standard strict.pm would never get loaded, so why did you write it? Now back on topic,
You still haven't addressed the problem I mentioned (and fixed) in my previous post. The second use will get executed first, and unconditionally. Since both use load the same module, all you'll get is a Subroutine baz redefined warning. However, it's skirting with danger. Furthermore, it doesn't really make sense to import raz and taz from 5.01 if you don't create replacements when loading from <5.01.
| [reply] [d/l] [select] |
by Firefly258 (Beadle) on Nov 10, 2006 at 02:24 UTC | |
by ikegami (Patriarch) on Nov 10, 2006 at 19:01 UTC | |
| |
Re^2: BEGIN and compile-time
by Firefly258 (Beadle) on Nov 10, 2006 at 14:28 UTC | |
Here eval"" always evaluates to false as use; returns nothing and we end up with the do BLOCK always being executed. But getting eval"" to return a TRUE value on a successful eval changes that.
| [reply] [d/l] [select] |
by imp (Priest) on Nov 10, 2006 at 19:17 UTC | |
| [reply] [d/l] |
by ikegami (Patriarch) on Nov 10, 2006 at 19:40 UTC | |
I like
Since require only returns true or an exception. The import can be done later, although I usually don't want to import from a dynamically loaded module. Update: Oops, silly me! Replaced eval "" with eval {}. Thanks tye. | [reply] [d/l] [select] |
by tye (Sage) on Nov 10, 2006 at 19:39 UTC | |
It is more appropriate to test $@. Oh, I disagree. There are too many cases where $@ doesn't survive. It is more fool-proof (and one of my "best practices") to check the return value of eval "....; 1" to determine whether or not eval failed (and then to use $@ to report what the error was, though $@ might no long contain this information). - tye | [reply] [d/l] |
by imp (Priest) on Nov 10, 2006 at 19:57 UTC | |
by tye (Sage) on Nov 10, 2006 at 20:01 UTC | |
by Firefly258 (Beadle) on Nov 11, 2006 at 03:42 UTC | |
Thanks tye for clearning up that little something, it made me take a closer look at sub VERSION. Here's an attempt to get use Module VERSION to load the right VERSION. It's kludgy and noisy but it works. | [reply] [d/l] [select] |
by ikegami (Patriarch) on Nov 11, 2006 at 10:43 UTC | |
You might get lots of redefined warnings. Other hard to debug problems might also surface. To avoid those, you might want to take CPAN's approach to determining a module's version. CPAN searches for $VERSION in the source and executes only that line (more or less). Since the module isn't actually loaded, no redefined problems, etc.
| [reply] [d/l] [select] |
by Firefly258 (Beadle) on Nov 11, 2006 at 18:49 UTC | |
A loader hook for @INC for explicit version control, basically just the above modified slightly. There's bound to be room for correction and improvement, especially to creating a simple and elegant data structure to house information about module and version numbers. | [reply] [d/l] [select] |