C++ wxWidgets Linux Win32 OS X Autoconf Bakefile Boost GCC GNU IMAP MSVC Perl Python SMTP STL TCP/IP Threads Unix ZSH

Diving into Modern Perl

Good Old Perl

While TT-Solutions is primarily a C++ company, we're not limited to just C++ and are reasonably fluent in several other programming languages, including the popular ones such as Java and C#. But while these languages are often chosen by our customers they are not the ones one would typically choose for a hobby project. Some of us like to use Python for those but, and even though I used Python several times and have nothing but good to say about it, personally I've always been partial to Perl, especially for quick and small programs. In fact, when I started using Perl in mid-nineties it was almost exclusively to write helpful one-liners and even though I used it to write several longer and more useful programs later, I still continued to think about it as not suitable for larger ones.

Partially this was due to my own poor knowledge of Perl that I simply picked up using what I knew of C, awk and shell languages. Mostly it was because I'm used to write larger programs in object-oriented style and while using Perl modules defining useful classes was never a problem, writing classes in Perl on my own always looked like an experiment in black magic with uncertain and possibly pretty dangerous results. And while I guess this could be explained by the same lack of knowledge on my part, there is no denying that writing object-oriented in Perl has never been as simple or natural as in, say, Python or C++.

For a long time I hoped that Perl 6 would change all this. Perl 6 would be a really wonderful language with features such as strong but optional typing, powerful parameter lists supporting just about any kind of constraints and not just type checks, excellent OO support with a very nice concept of roles, grammars as first-class language elements, built-in support for multi-dispatch and vector processing, Unicode support going beyond what any other language currently offers, several great features borrowed from functional languages including but not limited to currying and lazy evaluation and plenty of other smaller but still crazily convenient things such as chained comparisons and much, much more. And I still remain convinced that Perl 6 is the best and most innovative language, at least in the family of the imperative languages supporting object-oriented programming. However there is one problem with it: most things about it still need to be written in conditional tense. While not one but two compilers for Perl 6 already exist, neither of them is complete and both the compilers themselves and the programs generated by them are slow. Finally, the great collection of libraries, including wxPerl, that makes developing with Perl so easy is not yet available for Perl 6 neither. So I think it's still too early to start using Perl 6 and for now I can only with best luck to people working on it and continue to hope to start using it in the future.

The Future Is Now

But somehow, while I wasn't looking, some of the best parts of Perl 6 have trickled down to Perl 5. Undoubtedly the most important of them is Moose. Its official description as "A postmodern object system for Perl 5" may not sound very exciting but consider that it allows to define a class like this:

package TimeEntry;

use Moose;

has id         => ( is => 'ro', isa => Int, required => 1 );
has task_name  => ( is => 'ro', isa => Str, required => 1 );
has start_time => ( is => 'rw', isa => TimeStamp, required => 1 );
has end_time   => ( is => 'rw', isa => OptionalTimeStamp );

sub complete {
    my ($self, $end) = @_;
    $self->end_time($end // DateTime->now());
}
and without doing anything else you get a perfectly usable class whose objects can be created and used very naturally. In particular, Moose creates a constructor -- which checks that the values for all required attributes are provided and are of correct types -- and accessors (only getters or both getters and setters depending on the kind of the attribute, ro or rw) completely on its own.

Moose is often lauded for being much better than Perl built-in OO support and this is certainly true. However it is also simply very good on its own. Of course, the ability to easily define classes and attributes is only a small part of what it provides. It supports (even multiple) inheritance, of course, but also Perl 6-like roles which are similar but in several aspects nicer than interfaces in other languages. Its type system is still not comparable with the one of statically typed languages such as C++ but great for a dynamic language. New types are easy to define which encourages their use, for example TimeStamp and OptionalTimeStamp types in the snippet above are custom types which only needed to be defined like this:

class_type TimeStamp, { class => 'DateTime' };
subtype OptionalTimeStamp, as Maybe[TimeStamp];
Its attributes are more powerful than simple member fields as they can be lazily created, delegated and automatically coerced from values of types other than their own, and this is another reason for definition of TimeStamp above: we can simply add the declaration
coerce TimeStamp,
    from Str,
    via { DateTime::Format::RFC3339->parse_datetime($_) };
to allow using a date in RFC 3339 (similar to ISO 8601, i.e. YYYYMMDD HHMMSS format) anywhere a time stamp or optional time stamp are expected. Its methods can be overridden very easily thanks to the existence of before, after and around modifiers.

Beyond all this, Moose is a root of an entire ecosystem of related modules. It's impossible to describe all of them but a lot of them are very useful and some of them are simply magic. One of the latter is MooseX::Declare which allows to write the following even more amazing class declaration identical to the one above:

use MooseX::Declare;

class TimeEntry {
  has id         => ( is => 'ro', isa => Int, required => 1 );
  has task_name  => ( is => 'ro', isa => Str, required => 1 );
  has start_time => ( is => 'rw', isa => TimeStamp, required => 1 );
  has end_time   => ( is => 'rw', isa => OptionalTimeStamp );

  method complete(TimeStamp $end?) {
      $self->end_time = $end // DateTime->now;
  }
}
This looks even better: class is definitely more readable than package and using method instead of just sub is much more than a cosmetic change as it allow to get rid of explicitly extracting $self from the parameters list and to apply the type constraints to arguments (our original version didn't check that $end was of correct type at all).

MooseX::Declare might be a bit too magic for serious use: it's incompatible with some other modules and tools, notably many source filters; it results in copious amounts of incomprehensible error output for many common syntax errors putting to shame C++ compiler errors in deeply nested templates and it apparently has some non-trivial performance costs. Because of this I'm still undecided if it should be used in larger projects but it's certainly a pleasure to use if you can afford it.

There Is More to Being Modern

While Moose is a big part of what I meant by "modern" Perl in the title, it's not the only one. There are a lot of other smaller but important things, some of them not especially modern, such as always using warnings and strict and 3-argument form of open() and lexical file handles. Modern Perl is definitely also about using CPAN and likely about emphasizing testing and probably also about using Git and maybe even GitHub. Generally speaking, the term "modern Perl" is not strictly defined, if only because it obviously keeps changing, but, as the saying goes, you can easily recognize non-modern Perl when you see it.

Whatever modern Perl is, it would be impossible to speak about it without mentioning the book with the same title: Modern Perl by chromatic. It is a great introduction to Perl teaching just the right and best things about it. You won't find much about ties or typeglobs (although both are mentioned) nor anything at all about formats here but you will find a great introduction to OO programming with Moose and a great deal of excellent, practical information about all important aspects of Perl, including both the language itself, its libraries on CPAN and even the related tools. In spite of this, the book is unusually brief at less than 200 pages. It is also efficient: there is absolutely nothing to cut down. You rarely finish a technical book wishing that it were longer but this is exactly the feeling I had when I finished reading this one. Rereading it a couple more times helped a bit...

The "Modern Perl" book is available as a free download so there is really no reason to not read it (unless you are not interested in Perl at all but then you wouldn't be reading this neither), but I strongly encourage you to buy it -- or convince your company to buy it for you -- because it's largely worth it.

TL;DR Summary

To summarize this long article, my advice to anybody who wants to use Perl 5 is to read the Modern Perl book and look into Moose when writing any OO-code. If you had used Perl like me before, this will entirely change your perception of the language. For me this change was such that I even created my first ever CPAN module WebService::SlimTimer just because writing in Perl has never been such a pleasure before (and also because another modern-ish Perl tool, Dist::Zilla has made creating modules ready to be uploaded to CPAN so easy). I am still eagerly looking forward to Perl 6 but in the meanwhile modern Perl 5 is a very nice language to program in too.

July 7, 2022
wxWidgets 3.2, the latest stable release of wxWidgets, in development since several years, is finally available.
September 1, 2020
New gcc-warnings-tools script for C/C++ programmers for showing information about all the available warning options.
June 23, 2015
Release of where-included: a new tool for C/C++ programmers for finding the header file dependencies.
July 28, 2014
A new release of Bakefile, a makefile generator tool, is now available.
August 22, 2013
Added apache-splice-logs tool page.
March 31, 2013
Added new svn-to-git migration article.
August 6, 2012
Minor mladmin update: fix the script to work with recent Perl versions.
July 25, 2012
New diff-pdf tool description added.
April 27, 2012
wxWidgets training course proposed by TT-Solutions has been updated to cover version 3.0, please see training page for more information including the plan and some examples.
December 5, 2011
Another new script to help dealing with removing #pragma once from your code if needed.