2017 twenty four merry days of Perl Feed

Reindeer

Reindeer - 2017-12-20

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...


1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
10: 
11: 
12: 

 

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:


1: 
2: 

 

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:


1: 
 

has counter => ( is => 'ro', isa => 'Int', default => 0 );
 

You can write the same thing using a bunch of types like so:


1: 
 

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:


1: 
2: 
3: 

 

use Moose;
use MooseX::Attribute::ENV;
has home => ( is => 'ro', trait => [ 'ENV' ])

 

You can write:


1: 
2: 

 

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 and finally from Try::Tiny to give you handy try { ...} 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.

Gravatar Image This article contributed by: Mark Fowler <mark@twoshortplanks.com>