package Foo 1.00 should mirror use Foo 1.00

I recently suggested that Perl 5 extend the 'package' keyword to also set the package $VERSION:

package Foo 1.00;

In  a recent post, chromatic suggests that, according to Nicholas Clark's guideline for borrowing from Perl 6, extending 'package' should be done this way:

package Foo :ver(1.00);

I disagree.  A major problem with the multitude of ways to set $VERSION is that it doesn't necessarily correspond to how the 'use' keyword parses a module version restriction.

My strong belief is that any extension of 'package' should mirror 'use' in both semantics and style, like this:

# In a module
package Foo 1.00;

# Elsewhere
use Foo 1.00;

Having Perl parse both the same way guarantees congruence in the interpretation of the version numbers.

Extending 'package' in this way would require changes to toolchain modules, but since extending 'package' would only happen in a new version of Perl, it would be relatively simple to ensure that the toolchain modules in that version are changed as well.

The one big thing outside Perl itself that would need to change is the way in which 'alpha' distributions are designated on PAUSE/CPAN.  Rather than designating them through underscores in the distribution version (Foo-1.00_01), the release status designation would need to move into distribution metadata.

I think this would be a good evolution for CPAN as well as Perl.  The current method of handling alphas is kludgy.  It's hard (perhaps impossible) to specify alpha versions robustly in a 'use' statement or in distribution dependency data.  Version numbers should just be version numbers.  Release status should be managed separately.

While extending 'package' won't eliminate the historical problems with $VERSION on the thousands of modules on CPAN, it would at least put things on the right path going forward and I hope it becomes part of Perl 5.12 in the future.

This entry was posted in perl programming and tagged . Bookmark the permalink. Both comments and trackbacks are currently closed.


  1. Posted July 17, 2009 at 7:34 am | Permalink

    I would love to have an optional syntax which states "use this version of a module, but warn me if we get a newer version". This would mitigate a recurrent problem we have in our rather large code base where someone updates a module and things break in unexpected ways.

    As a bonus, it would search @INC for the right version, but that would be problematic as it would have to potentially load and discard packages several times. As I've discovered in the past, this is not only slow, but also prone to segfaults. If only Ingy's only module was more robust :/

  2. Posted July 17, 2009 at 9:42 am | Permalink

    I'm no fan of the Perl 6 style version moniker in Perl 5 myself; I prefer your version.

    There are two arguments for the Perl 6 style. The first, as you mention, is convergence between Perl 5 and Perl 6. It's possible to take that too far; :ver(1.01) is already different from :ver.

    The second is that the adverbial syntax lends itself to further extension. Adding an :author moniker is easier with the Perl 6 style syntax.

    Aesthetics and uniformity with the use directive are two arguments against it. I'm not sure which I prefer.

  3. brian d foy
    Posted July 17, 2009 at 11:52 am | Permalink

    If we can attach a version number to a package, the first thing I would want to do is distribution many versions of the code in the same file:

    package Foo 0.80;

    # really old code

    package Foo 0.90;

    # slightly newer code

    package Foo 1.00;

    # the latest code

    Then, when I have use, it would pick the right package and version.

    In Perl 6 land, I would want to extend this to author metadata too, but still have the ability to put it all in one file.

    This would me an extra scratchpad somewhere as perl compiles all of it or somehow scans through it to find the one to load.

    • david
      Posted July 17, 2009 at 1:41 pm | Permalink

      I discussed that at YAPC with Rob Kinyon a bit. I think it gets too tricky if multiple point in the code are using your module with different version requests. Either conflicts are fatal, which means code in file A breaks because file B asked for a newer version of Foo, which seems brittle, or else all code is loaded into versioned-namespaces. But that gets tricky for method resolution, as methods could be called on objects outside a scope that requested Foo of a particular version. Objects would need to be blessed not just into a namespace, but into a namespace and version. bless $self, "Foo", 1.00;

      I think it's something to consider, but I suspect it's going to be too tricky to wedge into Perl 5.

  4. Ed
    Posted July 17, 2009 at 4:22 pm | Permalink

    I certainly agree that the version number should be specified simply, the way it currently is on the use statement.

    Personally, the first additional functionality I'd like to see from that is, if the version is too old, perl should stop evaluating any more code in that file, until it finds a package statement that does match (like brian d foy suggests) or it reaches EOF. That way, it doesn't have to compile all of the packages until it finds one that works.

    With the version being set separately from the package declaration, one cannot necessarily do that effectively, because the $VERSION might not be at the top (I've worked with one individual who liked to set his $VERSION as the last thing in the module, so that he doesn't need a 1; at the end.)