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

";

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

";

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 with strict , 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 use if (@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 use if (%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 deprecated It 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 use split 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?