Perl-Sensitive Sunglasses | |
PerlMonks |
So, when assigning a value to $VERSION, do you use the old way or the new way? If there is a choice, the user must know the proper way to formulate numbers when refering to your module's version.
The thing between the module name and the list must be a v-string or numeric literal. Anything else is rejected by the parser, unlike the normal indirect-object syntax that can be overridden with braces even if it doesn't smell like an indirect object.# use VersionTest qw/1.2.3 foo bar/; # the above is no longer Kosher use VersionTest v1.2.3 qw/foo bar/; # do it this way (no comma).
For example, you cannot write:
use VersionTest '1.2.3' qw/foo bar/; #string my $needed= v2.3.4; use VersionTest $needed qw/foo bar/; #not a literal
If you don't write a sub VERSION, then your module inherits one from UNIVERSAL::, and that does a simple ge test.
So, if you expect to use the indirect-object form of version checking, your $VERSION variable must be a v-string or a floating point value using the three digit convension, explained below. If you use a literal such as $VERSION= '2.30.4', the old way, then the UNIVERSAL::VERSION function croaks with an error that '2.30.4' is not numeric, pointing to your caller's use statement. Not very useful, since the value it mentions isn't found anywhere where the error is reported!
Perl 5.6.0 used numbers for versions with this feature, with floating-point numbers encoding the version with three decimal digits per part. The idea was that version X.Y.Z would be represented as X+Y/1000 + Z/1000000. So 2.3.4 is the number 2.003004. That's why you had Perl version 5.005.
This is important because UNIVERSAL::VERSION will allow mixing of v-strings with floats by converting the v-string to a float using this convention.
So, if the module defines $VERSION=1.2 and you use Module v1.2 it will compare 1.2 against 1.002, which is not what you meant. If you reverse that and declare $VERSION=1.2.1 (v is implied if there is more than one dot in a literal) and then use Module 1.1, you will learn that 1.2.1 is less than 1.1, since the former is converted to 1.002001. The module will refuse to load since it is not a high enough version!
The lesson here is that if using numbers, not v-strings, always remember the 3-digit convension. It is improper to make a module version 1.2 (a floating point literal), unless you really did mean v1.200. Some modules do this wrong, and will cause this kind of surprise.
If you are using the normal Exporter::import function, this will call your module's require_version method. If you don't define one, you inherit one from Exporter. That implementation is surprising:use VersionTest qw/1.2.3 foo bar/;
It will do a numeric comparison between your request and $VERSION. What's '1.2.3' going to do with a numeric comparison? It will parse the floating-point value 1.2 and ignore the rest. Basically, it only looks at the first two parts, and silently ignores everything else! This is different from the indirect-object version check, which gives a "not numeric" error instead.
Worse yet, it will see a v-string as a numeric zero. So, if you have a v-string in $VERSION and you use the import-number form, your version check will always fail but no testing had been done!
Hmm, an old program uses this technique, and the old module had $VERSION='1.2'. The new module has $VERSION=v2.0.1, and you run your old program. It will report that you asked for 1.2 but the file contained version 0.0, and it won't load.
If you change from old to new when updating a module, and intend it to be backward compatible, it won't be if a user checks the version! New code, though, is expected to use the new form, isn't it?
With two incompatible forms, the user would have to know which to use, on a per-module basis. It's easy to figure out because doing it the wrong way results in a run-time error during the version checking code.
An easy solution would be to supply a require_version method that also uses the v-string in $VERSION but expects a old-style string as an argument. Do this with something similar to $requested= eval "v$requested"; VERSION($requested);
Symbol.pm says $VERSION = 1.02, which does not follow the 3-digit convension. This will give improper comparisons when using the indirect-object syntax.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Everything you wanted to know about Module Version Numbers and Checking
by Anonymous Monk on Aug 06, 2001 at 09:55 UTC | |
by John M. Dlugosz (Monsignor) on Aug 06, 2001 at 18:06 UTC |