Planet Moose - August 2014
Welcome to Planet Moose, a brief write up on what's been happening in the world of Moose in the past month, for the benefit of those of you who don't have their eyes permanently glued to the #moose IRC channel, or the MetaCPAN recent uploads page.
It's now a year since the first Planet Moose. I'm surprised I've managed to keep it up for a whole twelve months. (Though it's not always been posted promptly on the first day of the month!)
If you'd like to contribute some news for next month's issue, you can do so on the wiki.
Moose
Moose 2.1211 has been released containing some documentation updates and minor changes to Moose::Exporter.
More interestingly, three Moose 2.13xx trial releases have been uploaded to CPAN. The major new feature so far is improved support for overloaded operators, especially in roles, eliminating the need for MooseX::Role::WithOverloading.
Moo
Moo 1.006000 has been released. This has slightly improved performance for type constraint checks, and adds support for coerce => 1
in attribute declarations, provided you are using a type constraint framework that exposes an appropriate coercion API. (Type::Tiny does.)
OO Jenga
For some time there have been discussions on IRC about the problems of OO Jenga. For example, what happens when a Moose class subclasses a Moo class that subclasses a Class::Tiny class? Does it all work smoothly?
The major problem that tends to occur in this sort of situation is with BUILD
methods being called too early, or sometimes multiple times. Let's consider the case of a Unicorn class which subclasses Horse. Horse is built with Class::Tiny, and Unicorn with, say, Moose. So when you do:
Unicorn->new(name => "Twilight Sparkle", horn => "medium", colour => "mulberry");
then the first thing the Unicorn will do will be to call the parent constructor using something like:
$class->SUPER::new( \%params );
So now, Horse::new
gets called to handle the parameters it knows about (name
and colour
). Horse::new
is the constructor supplied by Class::Tiny. Once it's finished handling the parameters, what it will do is call a BUILD
sub in every level of $class
's inheritance hierarchy, starting at the bottom (i.e. just above UNIVERSAL). Once it's done that, then it returns $self
. This is where it gets interesting...
Unicorn::new
comes back into play. It handles the horn
parameter. Now that all the parameters have been handled, it now also calls the BUILD
sub in every level in $class
's inheritance hierarchy!
So all the BUILD
subs have been called twice. Horse wasn't aware that Unicorn was planning on calling them, and Unicorn wasn't aware that Horse had already called them. Whatsmore, the first time they were called, the horn
parameter hadn't been properly handled yet! Yowch!!
What can be done? Can't Horse::new
notice that it's been called by Unicorn::new
(a child class constructor) and thus avoid calling BUILD
? No, that doesn't quite work. The problem is that Unicorn::new
might need not call Horse::new
just once! Perhaps the Unicorn class definition includes something like:
has friends => ( is => "ro", isa => ArrayRef[ InstanceOf["Horse"] ], default => sub { [ Horse->new(name => "Pinkamena Pie") ] }, );
So a typical call of the Unicorn constructor might end up calling the Horse constructor once because Horse is the parent class of Unicorn, and again when it builds the default value for friends
.
There isn't really any neat solution to this. When calling the parent constructor, Unicorn really just needs to tell Horse on this particular method call, please don't call BUILD
. But how should Unicorn indicate this request? The solution that the developers of Moose, Moo, and Class::Tiny have settled on is to accept a parameter called __no_BUILD__
that tells the constructor not to call BUILD
methods.
So:
SomeClass->new( foo => 1, bar => 2, __no_BUILD__ => 1 );
will perform the normal SomeClass construction, but prevent BUILD
from getting called. It is not intended that you should ever supply this parameter yourself in normal code - it's merely a way for the various OO frameworks to co-operate with each other.
Expect to see this feature rolled out in Moose, Moo, and Class::Tiny over the next few months.
In other news...
- Dave Rolsky has published the slides from his Introduction to Moose class. It's been discussed on Hacker News.
- I released Type::Tiny 1.000000. I blogged about it a teeny tiny bit.
- Minor updates to MooseX::Role::Parameterized, MooseX::Storage, MooseX::Declare, and MooseX::Getopt.
- Minor update to Class::Method::Modifiers, a module used by Moo.
- An interesting article about German industrial giant Siemens' experiences with Moose at their office in Dresden.
*lol* at the easter egg :)