
john.peacock at havurah-software
Oct 6, 2008, 5:06 AM
Post #1 of 22
(5221 views)
Permalink
|
|
UNIVERSAL::VERSION and version.pm
|
|
Let me make something perfectly clear: I am not changing the external interface 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[1] the same way for every release of Perl. 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 DESCRIPTION): BEST PRACTICES 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 multiple decimals: 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> John 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
|