john.peacock at havurah-software
Oct 6, 2008, 5:06 AM
Post #1 of 22
Let me make something perfectly clear: I am not changing the external interface
UNIVERSAL::VERSION and version.pm
of the CPAN release version.pm for *any* reason. I am not having the arguments
all over again. Here's why: version.pm is now in the Perl core with 5.10.0.
The exact same code in the XS version of the CPAN release is in Perl itself.
This goes for the UNIVERSAL::VERSION code as well. So the CPAN release's only
reason for living is the allow people to 'use version' in any release of Perl
from 5.005_04 onwards and have it work exactly the same way for every release
The problem has always been that module authors have never understood $VERSION.
Before version.pm, it was *always* evaluated as a floating point number:
1.10 < 1.9
and that's that. The documentation always said to use two place decimals for
precisely this reason (see /Programming Perl/ Chapter 7). PAUSE has always
protected you, as a module author, from doing something stupid like the above.
Recently (as in two years ago?), Andreas has added the ability of authors to
"reset" their latest release, something that should not be done lightly.
The other thing that has never been clear to the vast majority of Perl users,
let alone module authors, is that this:
use module 1.2;
is magical. If and only if the first thing after the module name looks like a
number, which means the equivalent of /\d+(\.\d*)?/, then Perl itself will use
UNIVERSAL::VERSION to determine whether the module on disk meets that minimal
version. Anything else, like a quoted number, is assumed to be a parameter to
be passed to the module's import() routine. That's been there since the dawn of
time (AFAICT before 5.000).
However, while Perl was happily consistent about using numeric versions, the
rest of the open source community moved towards using MAJOR.MINOR.PATCH
multi-level versioning (aided and abetted by CVS's fsked-up $Revision$ string).
Thus was born the v-string in Perl 5.6.0, which was intended to be a way to
encode a multipart $VERSION into a simple scalar. It failed in that respect
(because it was too simple).
So, I spent a couple of years (no joke) trying to make v-strings work, but
failed (other than making v-strings be a magic variable rather than a simple
tokenizer hack). And then I spent several more years writing and perfecting
version.pm so that it Does The Right Thing in the purest Perl sense. But the
use of it by module authors does require reading the damn POD! Based on the
voluminous feedback on P5P, I added this paragraph right up front (after the
If you intend for your module to be used by different releases of Perl,
and/or for your $VERSION scalar to mean what you think it means, there
are a few simple rules to follow:
* Be consistent
Whichever of the two types of version objects that you choose to
employ, you should stick to either "Numeric Versions" or "Extended
Versions" and not mix them together. While this is possible, it is
very confusing to the average user.
In the case of Parse::RecDescent, Damian chose to ignore this advice, which is
what ultimately sparked the rant on we-hates-software.
I suppose I should write a page for PAUSE that explains what will happen if you
switch from numeric to extended versions (since it already scans for that). I'm
pretty sure that Andreas would put it up. The short answer is that, as an
author, if you have already released 1.94 to CPAN, you should either stick with
numeric versions (1.95, 1.96, etc) or if you really want to switch to an
extended version, go straight to v2.0.0. However, if you are starting from
scratch, you can use the qv() operator to DTRT for you, even if you don't use
1.10 < 1.9
qv('1.10') > qv('1.9') i.e. 1.10.0 > 1.9.0
qv() forces an extended version interpretation, even if there is only a single
decimal place. In hindsight, I wish I had never added that method, since it has
only served to confuse and irritate authors, who don't read the POD and assumes
it is a drop-in replacement for version->new().
In conclusion, every single idea discussed in the former thread has already been
discussed, /ad naseum/, in public on P5P over the last 8 years. I'm not willing
to reopen negotiations and in fact, given that the code is now inside Perl
itself, I cannot.
<TRON>END OF LINE</TRON>
1) Perl 5.005 cannot handle v-strings at all, so you have to quote the value for
new() or qv(). Perl 5.6.0 has v-strings, but the original representation
vanishes during tokenizing and version.pm has a heuristic that tries to guess
whether you meant to say 1.2.3 or not. It is still highly recommended to quote
your values, because then everyone is happy