Reindeer
This year the Elves at the North Pole had learned a lot about powerful packages they could load to improve Moose. The problem was that things were getting a little on the long winded size at the top of each of their Moose-based packages...
package ChristmasTree;
use Moose;
use MooseX::AttributeShortcuts;
use MooseX::AutoDestruct;
use MooseX::CascadeClearing;
use MooseX::ClassAttributes;
use MooseX::LazyRequire
use MooseX::StrictConstructor;
use MooseX::UndefTolerant::Attribute;
...
It was enough to make the Wise Old Elf's RSI flair up once more. Something had to be done. It was time for something better than Moose.
What's better than Moose for one of Santa's Elves? That's right: Reindeer. Still the same thing, but with more aerodynamic antlers.
The Reindeer module from the CPAN is a wrapper for Moose that not only loads Moose into your class but loads a whole bunch of handy Moose extensions too. In fact, the above code could simply be replaced by:
package ChristmasTree;
use Reindeer;
Does All The Things
Reindeer does so much that it's hard to document it all...
All our Favourite Extensions
Reindeer pulls in a bunch of modules that:
Provide syntax for abstract methods
Enable coercion by default (i.e. making it opt-out rather than opt-in)
Use shortcuts when writing attribute declarations
Provides currying for attribute delegation
Give you the ability to write class level attributes
Throw exceptions if you try to read an un-set attribute
Offer better syntax for overriding default values for attributes in subclasses
Throw exceptions if unknown parameters are passed to your constructor
Better construct anonymous classes with extra traits
Type Libraries
Reindeer exports a bunch of type libraries into your code. This means, for example, instead of writing your types as strings like so:
has counter => ( is => 'ro', isa => 'Int', default => 0 );
You can write the same thing using a bunch of types like so:
has counter => ( is => 'ro', isa => Int, default => 0 );
While these are just fancy no-argument function calls that return their own name (which are often inlined by the perl compiler) they act and feel like a real Perl syntax for types.
Not only do you save those two characters, but by using function calls instead of strings, you also get all the advantages of use strict
to catch typos at compile time.
Trait Aliases
Similarly Reindeer exports named traits (again, zero parameter functions, but actual implementations details aren't important.) So instead of writing:
use Moose;
use MooseX::Attribute::ENV;
has home => ( is => 'ro', trait => [ 'ENV' ])
You can write:
use Reindeer;
has home => ( is => 'ro', trait => [ ENV ])
As well as providing the slight reduction in typing, better typo checking, this also provides lazy loading of the trait classes - the first time the named trait is used the trait class will be loaded (this means there's no penalty for having the traits available if you don't use them.)
Extra Language Features and Extensions
Reindeer also enables a bunch non-Moose extra things that are either optional in Perl, or are standard extensions.
Enables all features for the version of Perl you're running. For example, if you're running 5.10 or later then you'll be able to use the
say
keyword.Provides
try
,catch
andfinally
from Try::Tiny to give you handytry { ...}
blocks.Cleans your namespace with namespace::autoclean so utility functions you import aren't callable as methods
Less Typing Is Less Mistakes
The Wise Old Elf was happy. He was well aware that a large amount of the code written by the Elves was written in the last few weeks before Christmas in a big rush. Not only would Reindeer act as a force multiplier for his development team making their work quicker, it would also reduce the amount of code they'd have to write, and hopefully therefore the number of chances to introduce bugs.