A nice little piece of Perl advocacy made the rounds of programming sites the other day. I recommend Fast, concise and reliable code? Try Perl!; it's simple, it's accurate, and it's reasonably free of bad advocacy.
Now read the comments on the Reddit Perl advocacy story. Ignore the grandstanding and Internet-based ruler-wielding contests. Ignore all of the posts that repeat a 45 year old APL joke (that wasn't funny in the '60s). Ignore all of the posts that pretend that software maintainability has anything to do with the presence or absence of sigils or the ability to iterate over a list more than one way or the requirement to indent your code instead of using braces, because those are the dumbest comments about maintainability and their only value is in identifying people who know so little about what makes software maintainable that you can ignore everything they say on the subject.
Read just the posts that say things like "Why doesn't Perl have function signatures?" and "You know, modules can be hard to install." and "The default OO system is very minimal."
Then read some of the responses.
Read them again. This time take off your I Heart Perl Advocacy hat. Close your IRC window to #perl on freenode. Read them one more time.
Are you sick of them yet? Good.
It's okay to say "Yes, all parameters to Perl functions get passed in a list you must explicitly unpack, but you can write your own validation code." It's not okay to say "You can write your own validation and unpacking code, so it's not a problem that you must write your own validation and unpacking code."
It's okay to say "Here are a couple of good CPAN modules that handle parameter unpacking and validation for you. They're efficient and they provide good syntax." It's not okay to say "The existence of those CPAN modules means that it's okay that after 15 years, Perl 5 still makes you unpack your arguments by yourself or install third party code to do so."
It's never okay to say "Why would you ever want to do anything other than unpack your arguments yourself?"
Perl is a great language. It has many great features. Its ecosystem is impressive, and I believe that many of its features compare very, very favorably to other languages and communities.
It's not perfect, however. The reference syntax is awful. The lack of function signatures is embarrassing. The minimal OO system is too minimal.
Ignoring these problems is bad advocacy. Dismissing these problems is bad advocacy. Telling people they're wrong for wanting good defaults (this being Perl, of course there are tuning knobs!) is hostile and malicious advocacy. If I were the sheriff of Perl Advocacy City, you'd end up wailing and gnashing your teeth in the outer darkness for lying to other people about Perl.
There's no Perl Advocacy City and I'm not the sheriff.
Even so, we should be honest about Perl.
It is wrong that you have to add two lines of boilerplate code to every module to ask Perl to help you write robust programs.
It is wrong that there is no declarative syntax for parameter passing in the core, 15 years after the release of Perl 5 and several years after the release of the relevant Perl 6 specification.
It is wrong that the default metaprogramming model of Perl 5 classes requires poking in package global variables and symbol tables, and even then method dispatch to overridden parent methods is very, very wrong in certain circumstances.
It is wrong that there is no way in the core to distinguish between methods and functions when performing reflection.
It is wrong that the syntax for defining a class in Perl 5 is to use the keyword
Perl 5 gets a lot of things right, but it gets all of these things wrong. They get more wrong every year that passes.
The Perlian Knot
Why do they remain wrong? There's no single reason; a big jumble of reasons feed into each other.
- Adding new keywords to Perl may be backwards incompatible in some cases, provided that someone actively upgrades to a new version of Perl, does not have adequate testing and change management strategies for existing code, does not read changelogs, is unlucky enough to suffer collisions of ambiguous barewords, and does not explicitly use core mechanisms to give the parser hints as to what's a keyword and what's not.
- Modifying the Perl 5 core means wading through a big wad of poorly-encapsulated C code strewn throughout with concise and easily confused macros that aren't self-documenting in any meaningful sense.
- The Perl 5 core wad of C macros has escaped to the DarkPAN because there's little enforced encapsulation between even the internal data structures used in the core and what embedders or extenders can manipulate.
- There's a backwards compatibility layer for this big wad of C code intended to run on at least three major versions of Perl 5, spanning the gap between a release in 2000 and the latest stable major release. (If the thought of maintaining that doesn't make you queasy, you might be the Buddah. More likely you need psychiatric assistance.)
- Despite a specification for the same features in Perl 6 (and existing implementations for both Perl 5 and Perl 6), no one has taken the time to create a plan to port those features to Perl 5, or write test cases for them, or identify limitations in Perl 5 as it exists to make certain features difficult, or even suggest a timeframe or milestone plan to implement them.
- Some people in the Perl 5 world don't even want these features.
- Despite the fact that refactoring the internals of Perl 5 has been a sore necessity since at least 1998, if only to provide a stable and well-encapsulated API behind which the guts can actually change, no one has provided a plan by which to do so.
- It's supremely difficult to tell whether a change causes test failures on other platforms because Perl 5 must run on several platforms where people have access to test results once a week (if not less frequently), where getting results is a manual process.
- Only a handful of people in the world know the core well enough to start to address some of those problems, and those people have day jobs and do not wish to work on the core full-time even for money.
- There's not enough money to entice anyone who already knows how to work on the core to do the cleanup work necessary to enable other people to work on the core.
- Even if there were, there's little obvious interest in other people in working on the core because there's little guarantee that any effort put into these areas would be useful. (Yes, I'm talking about myself here in part.)
- Even if there were hordes of volunteers willing to code new features or fix bugs, it's not clear that hordes of people are willing to help maintain these features or to stick around to ensure that the bugs stay fixed, especially on all of the platforms they need to stay fixed, especially as people find more and more corner cases that require you to revise code.
- Even if there were maintainers, it's not clear that anyone has the good taste or the time to refactor the system regularly to ensure that it's clean (especially as so much of the code is of the "Dear sweet Cthulthu, please don't touch this!" variety.)
- Even if there were ready volunteers willing to fix bugs and run tests and identify changes which passed several different compilers on several different platforms, there's still no roadmap. No one really guides the direction of development.
- Even if there were a roadmap, there's no schedule, so you can't even tell when you'll be able to use a feature or rely on a bugfix in a stable release.
- Even if there were a stable release schedule, the push toward backward compatibility in new code means that you can rarely rely on users having the most recent stable version of Perl available, so you must persist in your backwards compatibility workarounds and hacks until some point in the glorious future when you may be able to remove them and write clean, concise code again....
- ... which persists cruft and workarounds and brittle, fragile code that's difficult to maintain and difficult to understand.
I'm as guilty as anyone of contributing to this problem. I've written a few (thousand) tests, wrote a core library, fixed a few bugs, added a couple of features, and had a feature or two shot down... but the process is hugely demotivating.
I can point out flaws in every programming language I've ever used (and that's a lot) and design flaws in every programming language I've ever helped implement (and that's a few). That's not the point.
The point is that Perl 5 is missing some simple features present in almost every other programming language of its class, and the reasons why are not primarily technical.
I'm not sure how to cut this knot, except to say that Perl 6 suffers far different problems, namely that inventing the future is difficult to do even if we weren't working primarily with volunteer labor. That's why I spend precious development time working on Perl 6 and Parrot -- they're software where I can make a difference.
I wish I could say I could make a difference on Perl 5, but I'm not sure I can.