A deprecated feature in Perl 5 is a feature which is confusing, difficult to support, difficult to understand, difficult to use correctly, difficult to use safely, or an accident of implementation no one wants to maintain in the future.
There's no written deprecation policy for Perl 5. By rough consensus of practice, a deprecation notice must appear in at least one major release of Perl 5 before anyone can consider removing the deprecated feature. Thus deprecating, for example, the Switch module in Perl 5.10 means that it may not be a core module in Perl 5.12.
It may remain in core for Perl 5.12, but you the purpose of a
deprecation period is to encourage you to migrate away from it before the
release of Perl 5.12. (I chose this example deliberately; the
given
/when
construct backported from Perl 6 to Perl
5.10 obviates the need for the fragile Switch module. It's easy to
argue for its removal.)
Recent Deprecation Discussions
The issue of removing deprecated features comes up on p5p periodically. For example, George Greer suggested removing the Perl 4 pseudo-package separator; you can use the tick to separate package names like you use double-colons in Perl 5. Thus D'oh uses this old syntax where the modern syntax would be D::oh
.
Is this a problem? Tatsuhiko Miyagawa gave an example:
use strict;
my $name = "Joe";
print "$name's birthday is tomorrow\n";
Add the warnings
pragma for a hint at what might be wrong. If you're using anything older than
Perl 5.10, good luck at guessing at the problem -- Perl 5.10's warning message
expands the name of the variable to $name::s
, which is
substantially more helpful, if you know that '
is synonymous with
::
.
The correct way to write this code with interpolation is:
use strict;
my $name = "Joe";
print "${name}'s birthday is tomorrow\n";
That won't win any beauty contests. (Or should I say "That {won}'t win any beauty contests.")
On PerlMonks today, the hash reference question demonstrated code which worked but confused a novice terribly:
%package = ( 'zips' => {1,2,3,4} ); print %package->{zips};
You can dereference a hash (not a hash reference) with the dereferencing arrow, but if you enable warnings, you will receive the message:
Using a hash as a reference is deprecated...
A Selection of Deprecated Features
If you browse perldiag, you'll find several other deprecated features. Some of them are recent. Many of them have remained deprecated for several years. (Though it's tempting to put the Perl 4 pseudo-package separator in this category, it's more accurate to say that the Perl 5 syntax has superseded it for fifteen years.)
You won't get all of them; you have to dive into the source for all of them. Yet here are a few of my favorites.
Really old Perl let you omit the
@
on array names in some spots. This is now heavily deprecated.my @nums = 1 .. 4; push nums, 5;
This throws a compilation error about an undeclared
nums
when run withstrict
, but the code gets through the parser.Really old Perl let you omit the
%
on hash names in some spots. This is now heavily deprecated.This is similar; you can convince
keys
to operate on a hash if you omit the sigil as well.You have used the attributes pragam to modify the
locked
attribute on a code reference. The:locked
attribute is obsolete, has had no effect since 5005 threads were removed, and will be removed in the next major release of Perl 5.This message has been around for a while.
You have used the attributes pragam to modify the
unique
attribute on an array, hash or scalar reference. The:unique
attribute has had no effect since Perl 5.8.8, and will be removed in the next major release of Perl 5.After 5.10.1, it should be safe to remove both of these attributes from bleadperl (what will become 5.12).
defined()
is not usually useful on arrays because it checks for an undefined scalar value. If you want to see if the array is empty, just useif (@array) { # not empty }
.This message has been around for a while. It might be more useful as a parser syntax error.
defined()
is not usually useful on hashes because it checks for an undefined scalar value. If you want to see if the hash is empty, just useif (%hash) { # not empty }
for example.This message has been around for a while.
You used a declaration similar to
my $x if 0
. There has been a long-standing bug in Perl that causes a lexical variable not to be cleared at scope exit when its declaration includes a false conditional. Some people have exploited this bug to achieve a kind of static variable. Since we intend to fix this bug, we don't want people relying on this behavior.This is a newer deprecation; the
state
keyword added in Perl 5.10 provides a better way to declare and use static lexical variables in Perl 5.The
$[
variable (index of the first element in an array) is deprecated.I believe this is on the removal schedule for Perl 5.12.
Use of implicit split to
@_
is deprecatedIt makes a lot of work for the compiler when you clobber a subroutine's argument list, so it's better if you assign the results of a
split()
explicitly to an array (or list).Michael Schwern posted a patch to Remove implicit split to
@_
. As his message points out, this is another Perl 4 feature deprecated with the release of Perl 5.000 in October 1994.What's the problem? The use of
split
in scalar context. When you usesplit
that way, Perl 5 clobbers@_
with the list of results.This patch generated a lot of discussion.
You used the
package
keyword without specifying a package name. So no namespace is current at all. Using this can cause many otherwise reasonable constructs to fail in baffling ways.use strict;
instead.This message baffles me, but apparently you can get around declaring variables in some cases if you write
package;
.You tried to use a hash as a reference, as in
%foo->{"bar"}
or%$ref->{"hello"}
. Versions of perl <= 5.6.1 used to allow this syntax, but shouldn't have. It is now deprecated, and will be removed in a future version.I like how the code examples quote hash keys. This is a newer deprecation notice; it's only been around for eight years.
You tried to use an array as a reference, as in
@foo->[23]
or@$ref->[99]
. Versions of perl <= 5.6.1 used to allow this syntax, but shouldn't have. It is now deprecated, and will be removed in a future version.This has also been around for eight years.
The Deprecation Argument (and a possible solution)
The arguments for removing these deprecated features (with the appropriate deprecation period) are simple: they simplify Perl 5's internals, they remove confusing syntax corner cases, and they encourage people to write better code.
The arguments for retaining these features are likewise simple: modifying code may cause bugs and removing features may break existing code.
I have less sympathy for the con side; I find its arguments unconvincing. The arguments are especially thin as deprecating a feature means adding a warning for it. This means not only modifying code, but changing its behavior.
The problem, I believe, is that there's little impetus to migrate away from deprecated features; features can remain deprecated for 15 years. As well, there's too little feedback on the effect of removing deprecated features on existing code.
I ponder the existence of an alternate Perl 5 binary with deprecated features removed; would DarkPAN developers run it against their test suites and report any results where modifications are onerous? Would that provide sufficient data as to the effects of removing these features?
"Hello, is this thing on?"
Really, some of that stuff just has to happen. Ugh.
I don't think the danger exists, but I'd hate to see kurila followed as an example. Yes, perl can be made clean by removing everything crufty, but would we then trying to appeal to a market segment that isn't interested in Perl no matter what it does at the expense of people who appreciate why Perl is crufty? I think that would be a baby-with-the-bathwater scenario.
On the other hand, if a feature can be removed without breaking much of CPAN (and assuming that DarkPAN approximately follows CPAN, and knowing people don't shy away from old version of Perl where fears of upgrades exist) then it isn't much of a feature.
Let's just not go on a witch hunt for cruft in Perl because 1. we are going to find it 2. removing it won't accomplish what some might suppose.
-scott
Discussion starts on the p5p list; gets blogged about here; gets picked up by your identi.ca feed; gets replicated to Twitter; I read it and come back here and comment. Someone needs to clean up the Internet =P
@scrottie, I see a big difference between "deprecated for several years" and "everything crufty". If I put on my hat of Completely Ignoring Transition Costs, I'd like to see formats removed from the core keyword namespace, along with SysV shared memory. I'd like to see invariant sigils too.
Those aren't going to happen in Perl 5 any time soon, and that's okay. I can make a big list of those changes. Most of them are in Perl 6, which is part of the point of Perl 6.
Remember though that no feature is free, not in terms of maintenance, support, testing, documentation, training, and use. Removing deprecated features can reduce the cost of developing and using Perl 5. I don't believe that the Perl 5 community has a coherent idea of the costs of keeping them versus removing them; we could use one.
I wonder - who physically control the release process of perl?
@Samuraijack, those are the pumpkings. In general, each major family of releases has one committer responsible for deciding which commits from bleadperl to pick into maintperl for each release as well as when to release each release.
So long as deprecated features are well-documented, including what to do instead, and removed features are at least as well documented, I don't believe deprecating and removing duplicate features is normally problematic. Most of the examples you quote are excellent examples of this.
I don't see "You have used the attributes pragam to modify the locked attribute on a code reference. The :locked attribute is obsolete, has had no effect since 5005 threads were removed, and will be removed in the next major release of Perl 5" or anything similar in the perldiag page for 5.10.0, nor does it show up in any of the perl5[6-91]* delta pages included with perl 5.10.0.
Likewise, I see nothing about the :unique attribute going away in the same documents. (Perl 5.9.2 apparently disabled unique - but there was no indication that it wouldn't be corrected later.)
As many of the lesser coders out there program with warnings turned off, if it is not documented in either the release notes or the perldiag pages, it may as well be undocumented.
Even these two sound like it would be better for all concerned to eliminate them; I'm just concerned that you haven't notified the users as well as you think you have. I certainly wasn't aware of them being deprecated before this came up just now on your blog.