Legacy Feature Freeze

| 1 Comment

The first solution to bridging the gap between The Two Worlds of Perl Deployment is to segregate system Perl paths and application paths. As Zbigniew Łukasiak mentioned, one fine way to do this on your own is with the local::lib CPAN module.

The second part of the solution addresses a more subtle problem.

Language Feature Freeze

What would happen if you added a new method to Perl's UNIVERSAL package? I've run into that. I added the DOES() method, which went into Perl 5.10. Though isa() and can() already existed, with lower-case names, the pumpking argued that the possibility of a collision user-code which itself defined a does() method anywhere was too great to ignore. Thus the official way to check that a class or object performs a named role in Perl 5.10 is $invocant->DOES( 'role name' );.

What would happen if you added a new keyword to Perl? I proposed a patch to do just that, adding a class keyword to Perl 5. The patch is in limbo, even though it has tests and adds a nice new feature backported from Perl 6 and does not interfere with the existing test suite.

Of course, even if the patch ever were applied, you'd still have to enable the feature explicitly with use feature 'class'; or use 5.012; or even my own use Modern::Perl;. That's right: you don't get simple, declarative, compile-time class declarations in Perl 5 by default. You must explicitly request that the language help you.

That doesn't seem very Perlish to me, either.

Why is this a problem? What if someone from the "Must Never Change, Darnit!" camp wrote a Perl program in 1993 that needs to run, unmodified, today on Perl 5.10 (or 5.11 or 5.12)? What if that code defined a class function? (I hate writing parsers, but I'm decent enough at them that it only matters if that function has a prototype which makes it take a single function reference.) The stars just might align such that a sixteen year old program might behave differently under a modern version of Perl.

In other words, a modern version of Perl now, by default, behaves syntax-wise like a version of Perl released fifteen years ago.

I exaggerate slightly -- the our keyword is relatively new (only nine years old).

Old By Default is Wrong

The feature pragma exists so that you can enable new features in code which uses them. This is great if you don't want to touch code you wrote in 1993, but it can be a little tedious if you want the compiler to warn you about typos in variable names (a feature from around 1994), enable warnings about dubious constructs in specific lexical scopes (a feature from 2000), and so on.

The problem with the feature pragma is that it's exactly backwards. It freezes Perl's feature set to that of around July 2002 (give or take). Anything added in the past nearly seven years gets lumped into an alphabet soup of features you must explicitly enable. If you don't know that magic incantation, you don't get that feature. If you want to explain how to use modern Perl to a Perl novice, you have to deal with a big block of magic code they won't understand yet. So much for only essential complexity.

Remember that the goal is to ensure that code written before a feature was available even when running on a version of Perl which includes that feature.

A better alternative is to have feature limit the features you use. That is, a program written in 2002 for Perl 5.8.0 should specify that it uses only those features available in 5.8.0. That is, any code explicitly, declaratively, and lexically identifies the specific set of behavior it expects Perl to provide. Any code without such a declaration uses the default set of behaviors from the running version of Perl: by default, everything new.

I realize that this may require editing old code, but the problem's not nearly as bad as people make it sound. It won't affect most programs. The feature pragma currently enables only a handful of features. I can't search the DarkPAN to verify this, but I believe the chance of collisions is small. It also likely only affects programs running on Perl 5.12, as that's the first Perl version likely to include this.

The benefits are, to me, compelling. Couple this with library path segregation, and Perl 5 becomes much more robust in the face of CPAN installations and OS upgrades. Modern features are available to everyone, and not just the elite who understand how to enable them. Backwards compatiblity and future proofing becomes a declarative exercise in defensive programming. What's not to like?

1 Comment

Not for nothing, but couldn't you overload the use VERSION syntax for this?

That is, make C[use 5.6;] implicitly do a C[no feature A; no feature B; no feature Q;] to "roll back" the syntax to whatever version.

That feature has been around for an awfully long time, and is pretty popular, and injecting that into the source, or putting C[-M5.2] in the shebang line doesn't seem particularly onerous. Certainly it would be easier to look up the development date ('93 you said?) in a table and add the corresponding version number than to try and debug what feature is in conflict with that Elbonian dictionary module that you have the only remaining copy of.

Modern Perl: The Book

cover image for Modern Perl: the book

The best Perl Programmers read Modern Perl: The Book.

sponsored by the How to Make a Smoothie guide



About this Entry

This page contains a single entry by chromatic published on April 16, 2009 10:49 PM.

Reconciling Bicameral Perl with Library Paths was the previous entry in this blog.

The Value of a Warning is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Powered by the Perl programming language

what is programming?