[I don't know if the attributions here are accurate; my apologies]

Randy W. Sims wrote:

On 4/4/2004 5:14 PM, Ken Williams wrote:

On the other hand, versions have always been required to be contained
all in one line, so maybe we should insist that people change their
code to:

use version; $VERSION = version->new("12.2.1");


I can't remember. Is this carried out before or after requirements processing in M::B? I ask because it's possible that version.pm is not present on perl < 5.8... Well, that's a minor issue.

The CPAN release of version.pm (currently 0.37) runs everywhere back as far as 5.005_03, but it would be an additional requirement to M::B, which isn't necessarily a bad thing, but a consideration. However, if people are starting to 'use version' in their code to explicitely code their $VERSION globals, then M::B (and ExtUtils::MakeMaker) are going to have to deal with it in some fashion.


The safest way to do that is to mandate that the $VERSION code remains on a single line, _including any supporting modules if required_, as suggested above. This is also the easiest, since by definition, if a module is going to rely on version->new, then version.pm will be present in some form for M::B or EU::MM to use as well. I am not opposed to seeing M::B using version.pm itself, now that I feel that the interface changes in version.pm are pretty much at an end (with 0.37). However see below for some possible future directions in $VERSION...


If there is any way possible, I wish we could find a way to eliminate $VERSION hacks. I really don't know enough about the issues involved, but can't we scan the whole file recording every occurence of $VERSION (noting that there can be multiple packages in a file), and run it through a few rules to come up with an educated (probabilistic) guess?

The "version" module attempts to perform all conceivable version comparisons in a consistent and predictible fashion, by converting everything used as a version into a version object. $VERSION is a special scalar, on par with any of the magic punctuation scalars, even though it looks like an ordinary user-space scalar. It is, I believe, the only Perl-level scalar referred directly by the C-level Perl code by name (again other than the punctuation scalars).


Consequently, $VERSION handling is always going to be somewhat different from all other scalars. And, given that both M::B and EU::MM are attempting to load a module without really loading it, just for the purposes of judging that module's $VERSION, I don't see any way around the current level of magic/hacks.

As for the future, the patches I am slowly working on for Perl 5.9.x/5.10.0 (which are by no means guaranteed to be accepted) will make things even easier/more magical. I have code which makes the $VERSION scalar in 5.9.x+ fully magical, in that this:

$VERSION = 1.2.3;

will automatically instantiate the scalar $VERSION as a version object. This is the easy part; making that functionality exist in the compatibility module is harder. I do have a way to do it (in testing) involving tied variables, but I have not finished design (I've been fighting with other issues, like default stringification rules).

If I was writing M::B and EU::MM (which I am not, thanks!), I would do the following psuedo-code:

        'use version' in M::B EU::MM directly
        find the first line containing an assignment to the scalar $VERSION
        eval the right side
        if the result is not a version object, make it one
        keep the $VERSION as an object for comparison purposes
        stringify $VERSION only when required (say for the dist filename)

The biggest feature of the version.pm object code is the consistent comparison of all version-like values, whether they are defined with 1, 2, or more decimal seperators.

One thing that came up in the recent P5P discussion of versions and stringification was the idea that version.pm could offer a custom function which could be used to extract $VERSION from a random module, something like

$mod_version = version->from_module("modulename");

which would return a version object for later use. This would relieve both M::B and EU::MM from maintaining their own code for that purpose (and I think there was a third module that had it's own routines to do this). I am willing to work (with others) on developing a common function to do this. Would that help?

John

--
John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Boulevard
Suite H
Lanham, MD  20706
301-459-3366 x.5010
fax 301-429-5748

Reply via email to