Before Moose 2.1000, Moose's Num type used Scalar::Util::looks_like_number, which recognizes
" 1223  ", NaN, Inf, "0 but true", etc. as numbers. In future releases, Num will only accept "123", 123, "1e3", 1e3, ".0", "0.0" etc. You can still get the older behaviour by using the LaxNum type provided by the MooseX::Types::LaxNum module. Please see this RT ticket for more details.

We don't depend on 1/2 of CPAN, 1/2 of CPAN depends on us!

Well, not really, but the new Map of CPAN website created by Grant McLean provides some pretty awesome (and quite telling) visualizations.


Modules that depend on Moose (give it a few seconds to load).

Moose 2.02

It's almost July, which means that it's time to start looking at the next major release of Moose, 2.0200. In addition to the changes that have been released in the minor revisions of the 2.00 series, this release will also include some additional, larger changes, the main ones being type constraint inlining and some changes to the way we generate inlined methods.

Type constraint inlining

When you define a type, you typically only specify how the type differs from some parent type. Currently, as a way to speed up type constraint checking, you can use the optimize_as option to define a validation subroutine to be used in place of checking the parent constraint followed by the current constraint's check. This helps, but could be better.

In 2.02, you will be able to use the inline_as option instead, to define a code snippet to use when inlining this type constraint, avoiding even the subroutine call overhead in accessors and constructors. Based on some simple benchmarks, this speeds up accessors by 30-40% and constructors by 10-30%, depending on the type constraints used and what else the methods are doing:

Moose 2.00
------
Benchmark: timing 500000 iterations of accessors_simple, constructor_simple...
accessors_simple:  4 wallclock secs ( 4.41 usr +  0.00 sys =  4.41 CPU) @ 113378.68/s (n=500000)
constructor_simple: 18 wallclock secs (17.83 usr +  0.01 sys = 17.84 CPU) @ 28026.91/s (n=500000)
Benchmark: timing 20000 iterations of accessors_all, constructor_all...
accessors_all: 12 wallclock secs (11.92 usr +  0.01 sys = 11.93 CPU) @ 1676.45/s (n=20000)
constructor_all: 12 wallclock secs (11.85 usr +  0.01 sys = 11.86 CPU) @ 1686.34/s (n=20000)

Moose 2.02
-----
Benchmark: timing 500000 iterations of accessors_simple, constructor_simple...
accessors_simple:  3 wallclock secs ( 2.70 usr +  0.01 sys =  2.71 CPU) @ 184501.85/s (n=500000)
constructor_simple: 15 wallclock secs (16.15 usr +  0.00 sys = 16.15 CPU) @ 30959.75/s (n=500000)
Benchmark: timing 20000 iterations of accessors_all, constructor_all...
accessors_all:  8 wallclock secs ( 7.45 usr +  0.01 sys =  7.46 CPU) @ 2680.97/s (n=20000)
constructor_all:  8 wallclock secs ( 7.73 usr +  0.01 sys =  7.74 CPU) @ 2583.98/s (n=20000)

Because inline_as provides all of the functionality that optimize_as provided, optimize_as will be deprecated in 2.02, and eventually removed.

Method generation

Constructors and accessors are generated as closures. For instance, when you pass "default => sub { ... }" as an attribute option, that sub is saved, and then closed over when the accessor is generated (if the attribute is lazy), something along the lines of:

my $default = $attr->default;
my $code = eval "sub { ... }"; # this uses $default
$meta->add_method($attr->name => $code);

Previously, we used to close over a lot of meta-objects directly, out of convenience, but this makes deparsing hard because of the many links metaobjects have between each other (try using Data::Dump::Streamer to deparse a Moose-generated constructor!). More importantly though, this gets in the way of some future optimizations we're hoping to be able to do.

The actual effects of this are mostly only visible if you're writing extensions that require using the closed-over variables that were removed ($attr, $meta, $type_constraint_obj, etc). If you were, you'll have to either adjust your inlining code to use the new variables that are provided, or override the environment that Moose uses when compiling generated methods to add them back. Feel free to stop by #moose if you have questions about how to do this.

Finally, one obstacle to this being complete is that initializer subs receive the attribute metaobject as a parameter, which means we can't avoid closing over it in that case. This behavior is now deprecated, and will be removed in the future.

Other changes since 2.0008

  • The Array native trait now has a first_index delegation, which works just like first except that it returns the index of the match rather than the match itself.

Summary of changes during the 2.00 release cycle

  • Type constraint error messages now use Devel::PartialDump when possible, to display the data that failed the type constraint.
  • Anonymous packages are now possible, via Class::MOP::Package->create_anon.
  • The methods we generate are now much better about storing definition contexts, so there should be a lot fewer instances of "generated method (unknown origin)".
  • Many bug fixes (see the Changes file for a full list).

Conclusion

Please install the current release candidate (Moose 2.0102) from CPAN, and report any issues it causes with your code. If all goes well, Moose 2.0200 will be released on July 18.

Moose Class at YAPC::NA 2011

I'll be offering a one day Intro to Moose class at YAPC::NA 2011 in lovely Asheville, NC. To register, log in to the YAPC::NA site and then go to purchasing page. If you haven't registered for YAPC yet, you can buy your conference ticket at the same time too.

Intro to Moose

Join us for an interactive hands-on course all about Moose, an OO system for Perl 5 that provides a simple declarative layer of "sugar" on top of a powerful, extensible meta-model.

With Moose, simple classes can be created without writing any subroutines, and complex classes can be simplified. Moose's features include a powerful attribute declaration system, type constraints and coercions, method modifiers ("before", "after", and "around"), a role system (like mixins on steroids), and more. Moose also has a vibrant ecosystem of extensions as seen in the variety of MooseX:: modules on CPAN.

This course will cover Moose's core features, dip a toe into the meta-model, and explore some of the more powerful MooseX:: modules available on CPAN.

Students are expected to bring a laptop, as you will be writing code during the class. You will also be provided with a tarball a week or so before the class is scheduled, which will contain a directory tree skeleton and test files.

Moose's Perl version support policy

The release of perl 5.14.0 (and the simultaneous dropping of support for the perl 5.10 release series) is probably a good time to start looking at the support policy for the future of Moose. In particular, we do not yet have an official policy for the versions of perl we support.

For a historical perspective, Moose has required perl 5.8.1 since 2008 (at which point, 5.10.0 was the latest released version of perl). The requirement was bumped to 5.8.3 within the past year due to test failures on 5.8.1 (and none of the dev team having access to anything below 5.8.3), a move that met with basically no complaints.

Today, the latest released version of perl is 5.14.0. Relatedly, the earliest version of perl still supported by the perl5-porters is 5.12.0, and the earliest version of perl shipped with the latest release of any major Linux distribution except CentOS is 5.10.1 (and CentOS 6 should be released with 5.10.1 by the beginning of June). Supporting back to 5.8.3 now requires supporting 4 major releases (and 13 minor releases) dating back 7 years, and this isn't a very sustainable position to be in, given the limited resources of the Moose dev team. With new major releases of perl coming out yearly now, this will easily become overwhelming soon.

So with that in mind, Moose will be dropping support for perl 5.8 with the 2.06 release (in January of 2012). This will allow enough time for CentOS to get a stable release out that contains perl 5.10.1, and so everyone still running perl 5.8 should have an officially supported upgrade path by that point. As for what this actually means: we will not be immediately rushing in to start using smart matching and ripping out our existing 5.8 compatibility code. The specified version requirement will stay at 5.8.3. Moose will likely continue to work on perl 5.8 for a good while after next January. What this does mean, however, is that we will not be spending any more time fixing 5.8-specific issues. If critical bugs are found (unlikely at this point, but still possible), we will likely just bump our version requirement if no patch is forthcoming. New features are a fuzzier topic, but if someone comes along and implements a new Moose feature that requires features in perl 5.10, that patch will likely be accepted.

Our official support policy has been updated with this new information, and will be released with the next Moose release; it can be viewed here. If you have any questions about this policy, feel free to stop by #moose on irc.perl.org or contact the Moose mailing list at moose@perl.org.

Moose 2.0 Release Candidate

As you may have noticed, there has been a bit of a delay in getting Moose 2 out. We've been doing a lot of testing, and a lot of fixing up of the Moose extensions (and a lot of being busy with things other than Moose), but we're finally ready for a release. Moose-1.9906-TRIAL has just made it to CPAN, and this will hopefully be the last dev release before 2.0000. If you've been holding off on testing the new Moose versions until things settle down and everything works again, now is the time to actually do that. If no serious bugs are reported in the next week or so, Moose 2.0000 will be released on Monday, April 11.

As mentioned earlier, this release includes some major refactorings of the internals. Therefore, a lot of MooseX modules had to be updated to take this into account. All of the latest versions of the MooseX modules should now work with both the current stable release, and the latest dev release of Moose, so you can upgrade all of these without any breakages.

The inverse of this is not true, however - many old versions of Moose extensions will break if you upgrade Moose without also upgrading them. When you upgrade to Moose 1.9906 (or Moose 2.0000), the installation process will warn if there are any outdated modules installed on your system that may stop working with the new Moose. Upgrading these modules is important in order to make sure everything continues to work. To make this process easier, Moose now ships with a script named 'moose-outdated', which scans through your system and prints the names of any modules it finds which conflict with the currently installed version of Moose. After upgrading Moose, a simple 'moose-outdated | cpanm' should bring you up to date. This functionality will continue to be provided and kept up to date in future versions of Moose.

Finally, I'd just like to highlight again the issue that Dave brought up in the previous post - make sure you aren't expecting role attributes to pick up the attribute metaclass of the class they're being applied to, as this will no longer happen. Read the previous post for more details about this.

Comments, questions, or issues with the Moose release candidate should be directed to #moose on irc.perl.org, the moose@perl.org mailing list, or Moose's issue tracker on rt.perl.org.

We're getting closer and close to releasing Moose 2.0, and I wanted to highlight one particular change in Moose 2.0.

MooseX modules whic affect attributes, like MooseX::SemiAffordanceAccessor and MooseX::LazyRequire, now have different behavior in conjunction with roles.

When you use one of these modules in your class, it applies a trait to all of the attributes defined in your class:

package MyClass;

use Moose;
use MooseX::SemiAffordanceAccessor;

has foo => ( is => 'rw' );

In this example, the foo attribute ends up with the MooseX::SemiAffordanceAccessor::Role::Attribute trait applied to it behind the scenes. This trait is what affects how accessors are named.

With the current version of Moose, these attribute traits are also applied to attributes provided by roles:

package MyClass;

use Moose;
use MooseX::SemiAffordanceAccessor;

with 'MyRole';

has foo => ( is => 'rw' );

Any attributes provided by MyRole end up with the SemiAffordanceAccessor naming scheme.

This is a huge stinking bug. The problem is that by applying this trait, we have changed the interface provided by MyRole. One of the major uses of roles is to provide a named interface, so this is bad.

With Moose 2.0, this bug is fixed. When we apply MyRole, the attributes applied from the role no longer acquire the attribute traits of the consuming class.

However, some people might have been taking advantage of this feature, writing roles with the assumption that the consuming class uses a MooseX module.

The right thing to do is to use the relevant MooseX module in the role itself. This is not possible with Moose 1.2x, but will be possible in Moose 2.0. The only catch is that the MooseX module has to explicitly support this.

For many modules, this is trivial. Let's take MooseX::SemiAffordanceAccessor as an example. The code used to look like this:

Moose::Exporter->setup_import_methods(
    class_metaroles => {
        attribute => ['MooseX::SemiAffordanceAccessor::Role::Attribute'],
    },
);

To make it work with both new and old Moose, it becomes:

my %metaroles = (
    class_metaroles => {
        attribute => ['MooseX::SemiAffordanceAccessor::Role::Attribute'],
    },
);

$metaroles{role_metaroles} = {
    applied_attribute => ['MooseX::SemiAffordanceAccessor::Role::Attribute'],
} if $Moose::VERSION >= 1.9900;

Moose::Exporter->setup_import_methods(%metaroles);

Some MooseX modules don't have it so easy. If your MooseX applies traits to the class metaclass as well as the attributes, making it work with roles is much harder. We're planning to make this simpler in Moose 2.02, but for now your best bet is to look at a module like MooseX::Attribute::Deflator for an example of how to do this. Basically, you have to have the role "pass along" the class metaroles when the role is applied.

As a consumer of a MooseX module, updating to Moose 2.0 will be fairly simple. If you want to apply a MooseX module to attributes in role, just use the module in your roles.

We're currently working with MooseX authors to get their modules updated in preparation for the Moose 2.0 release.

We're available on irc://irc.perl.org/#moose-dev to help you update your module, or you can email us at moose@perl.org. Please contact us if you need help updating your code.

The Moose Ecosystem

I was browsing Planet Perl Iron Man over the holidays and reading many of the "Year in Perl" recaps as well as the "Perl in 2011" predictions. One in particular caught my attention, that is What I would love to see in 2011 for Perl by claudio in which he has many nice words to say about Moose and the Modern Perl movement in general. As I started to read the comments I noticed one from brian d foy in which he said:

Note, though, that calling Moose "the preferred OO framework" is a bit of puffery. Some people prefer it, but I'll bet you most Perlers have never even looked at it. Not only that, the fragmentation of Mouse, Moose, Moo, and whatever else out there is starting to confuse people who haven't started yet (so it's a frequent question I get).

Of course from inside the Modern Perl/Moose bubble it is hard to believe that people haven't heard of Moose. And while I do think Moose is seeping out more and more, brian, with his unique position of being a well known figure both inside and outside of the Perl community, is very much right about the confusion over Moose, Mouse, Moo, et al. So after much discussion with the other core Moose team I decided it was time to write a blog post to help clear things up.

Clearing up the Confusion

So of course we (the core Moose devs) believe that Moose is the best choice, but we are not so ignorant as to believe that Moose is the right choice for everyone and every environment. And it was this exact reason that brought about Mouse and which is currently driving the Moo effort. Additionally Moose has always tried it's best to not make you pay for features you don't use by doing things like compiling highly focused accessors and lazy loading features when possible, which, when taken to the extreme leads to modules like Class::Method::Modifiers and Role::Basic in which Moose features are extracted completely.

So how does all this fit into the Moose ecosystem??

Moose vs. Mouse

So as I said, we think Moose is the best choice, but when Moose is prohibitive, either because of startup overhead or memory usage, then Mouse is currently the best choice and one we encourage. Period.

In reality, there is no fragementation here because Mouse is very much commited to maintaining surface Moose compatability and runs a fair portion of the Moose test suite successfully (minus the Meta-Object tests of course).

Additionally tools like Any::Moose allow you to defer your decision and/or provide both options when possible. There have even been a few MooseX:: modules ported to MouseX and while this practice is generally discouraged because there are simply too many moving parts to keep in sync, the need existed and so people obliged.

In the end, what is important for us is that people are writing good OO code following the guidelines that Moose encourages. If, for whatever reason, they need to use Mouse to do that, it is okay with us. At least for now that is ...

So what about Moo?

Ever since the early days of Moose we have been searching for ways to make Moose startup time faster. Recent heavy profiling by core Moose devs, Jesse Luehrs and Dave Rolsky, has lead to some pretty hefty speed-ups and plans for even more in the future. But we know that there is only so far this path can take us.

And then we come to mst and Moo.

Moo is an experiment from the sick and twisted mind of mst to radically re-think how Moose goes about compiling all it's meta objects. It builds on ideas from even more experimental MooseX::Compile born from the equally twisted mind of Yuval Kogman and an earlier mst experiment called MooseX::Antlers.

While mst and a few other brave souls are actually using Moo successfully, it is currently only in very limited situations with very simple "baby" Moose code. And really in the end, if Moo succeeds, you won't even know it is there because it will just be part of how Moose does it's thing. It is at this point that the community may choose to deprecate Mouse, but we will cross that bridge when we come to it.

So again, no real fragmentation here either, it is all part of the grand plan.

Moose inspired

The Perl community has long prided itself as being an group of independent minded (cough stubborn cough) people who don't just jump on the shiniest bandwagon or take the easy way out. We are well aware that Moose is a lot of Kool-Aid to drink and is not the right choice for everyone. And obviously because of this Mouse is not useful to these people either. So this is where some of the Moose inspired modules come into play.

In some cases these modules are re-implementations of Moose features, in other cases they are parts of Moose that have been extracted because of their usefulness to others outside of Moose. Here is a short, totally noncomprehensive list ...

As we said above, the ultimate goal of Moose has always been to make writing good OO code in Perl a less tedious and repetitive process. While we think Moose is the best way to do that, it is understandable that sometimes you only need a small part of it and all these modules provide this. And really as long as they maintain some level of commitment to Moose compatability, this works for us because it still serves our ultimate goal.

So sure, a little fragmentation here, but with a compatability commitment these really just become gateway modules to Moose.

Moose itch scratching

And lastly, I wanted to touch on the number of modules that have been in some way inspired by or related to Moose development. This subject really deserves it's own blog post, but I think it is worth mentioning these modules.

Conclusion

So hopefully this helps clear up some of the confusion that brian has seen on his adventures outside of the Modern Perl bubble. One of the really interesting and beautiful things about Open Source software development and the CPAN community in particular is that it really is a true meritocracy and functions extremely well as highly organized chaos. The drawback to that is that sometimes we have to clear up some confusion like this, which when viewed against the benefits is not that bad at all.

Happy New Year!

The Future of Moose

A complaint that has come up multiple times over the past few months is that, as important as Moose is becoming in the Perl ecosystem, it should be more concerned with backwards compatibility. After a series of discussions, the Moose development team has come up with a support policy that seems to satisfy most people; you can read about it here. The main points are: Moose will be moving to a time-boxed release cycle of three months between (major) releases. Bug fixes and minor features can be added in between major releases as long as they don't break backwards compatibility (and we will put more effort into making sure they don't). Major releases can break backwards compatibility, but we will release at least one (ideally more than one) trial release before the actual release comes out, so that people can test their own systems with the new features, and report back with issues they may have. We will also do our best to assist maintainers of Moose extensions with updating their modules for major changes, but not to the point of taking over maintainership of extensions that have become unmaintained. If you rely on a Moose extension whose maintainer has abandoned it, feel free to find someone willing to take up maintainership, and come talk to us on #moose, we'll be more than willing to help you get up to speed.

Now, on to the fun part(: The next Moose release will contain several exciting new improvements, both for users and extension authors. The first is that there has been a significant effort to speed up Moose's compilation time, through several means. The largest and most obvious is that Package::Stash, the module that Moose uses to do its symbol table manipulation (for adding and retrieving methods, among other things), has been rewritten entirely in XS. Since Moose spends over a third of its compilation time doing symbol table manipulation, this seemed like a good optimization target, and this turns out to have been correct - it resulted in a 10-15% speedup across the board for Moose application compile times. Another advantage to this is that it fixes a couple (admittedly minor) long-standing bugs in the Class::MOP::Package API, since the symbol table API available from pure perl has several inherent issues itself. Another area that should see significant improvement is in code which uses the native delegation attribute traits. Previously (ever since the rewrite in 1.15), the traits themselves were loaded lazily (i.e. Moose::Meta::Attribute::Native::Trait::Bool wasn't loaded unless you actually declared an attribute with traits => ['Bool']), but the implementations of each native delegation were all loaded at once, when the trait itself was loaded. This has been fixed, and should be another fairly large speedup for applications which use only a couple native delegations from the traits they use (which is the case the vast majority of the time). Finally, the way method metaobjects are cached has been improved, which speeds up the introspection of methods (which happens frequently during compilation) a small but noticeable amount. Here are some links to some relevant profiling data (run on my netbook under full profiling, which is why the times are so high): "perl -MKiokuDB -e1" with Moose 1.19: 8.60s, "perl -MKiokuDB -e1" with Moose git: 6.38s, "perl -MMarkdent::Simple::Document -e1" with Moose 1.19: 13.9s, "perl -MMarkdent::Simple::Document -e1" with Moose git: 10.6s. These changes should have minimal compatibility impact (and none at all if you don't use the Class::MOP::Package API); a more detailed discussion is in Moose::Manual::Delta.

In terms of features, we have made a fairly significant change to how attribute metaroles work. Previously, when a role was applied to a class, it would copy the attributes from the role into the class using the class's default attribute metaclass, prior to applying the traits specified in the attribute definition. This is obviously incorrect with a bit of thought - attribute metaclasses completely define how the attribute works, including things like how accessors are generated. If a role contains an attribute and some methods, those methods need to be able to know what method name the accessor is going to be installed under, or the role won't work. A good example of this is a class which uses MooseX::FollowPBP consuming a role which doesn't - currently, this completely breaks the role. With this change, roles now have their own default attribute metaclass, separate from any class. This also allows for an additional feature - when writing extensions, you can specify the 'applied_attribute' option to the 'role' block in 'apply_metaroles' to specify a set of default traits that all attributes defined in that role will receive when they are applied to a class. This should work identically to the 'attribute' option in the 'class' block, and should allow extensions which add default attribute metaroles (such as MooseX::Aliases) to work identically in both classes and roles (unlike currently, where the trait must be applied explicitly in role attributes). The downside to this is that it breaks backwards compatibility in a potentially confusing way: if you were assuming and relying on role attributes using the class's attribute metaclass, your roles will break, and there isn't really a way to detect this. The solution will be to use the same extensions in your roles that you do in the classes that consume those roles, but as noted previously, attribute metaroles don't currently work in roles. These extensions will be fixed by the time we make an actual release.

Finally, there is also some good news for extension authors: the inlining API should be much more sane, and the code itself should be much more readable, so adding inlined method generation support to your modules which affect accessor or constructor/destructor generation should be much, much easier now. Some highlights include: the attribute metaclass and class metaclass controlling entirely how the bodies of the methods they generate are created (so there should no longer be a need to write accessor or constructor metaclass traits), accessor generation in Class::MOP and Moose going through one much simplified codepath (read: removed the obscene amount of code duplication between Class::MOP and Moose), so figuring out how a given accessor is generated should be pretty trivial now, and constructors now asking the attribute metaclass how to initialize attributes at construction time, rather than doing it themselves with a bunch of duplicated code (so in the case of simple attribute traits which affect accessor generation, manually modifying the constructor generation shouldn't even be necessary). The downside to this is, as you may have guessed, the API for doing code inlining has been changed pretty radically. This will require some work on the part of extension authors, in order to use the new API (since there's not really a non-insane way to support both APIs), but again, we'll be working with extension authors to make sure this happens before our actual release, and we'll be releasing a few dev releases prior to the actual release to allow people with non-CPAN code to have a chance to update their code.

As far as a plan goes, we're looking to have our first trial release out by the end of this month, and are aiming for the actual release to happen sometime in late December or early January. If you have any questions about the new release and support process, or about any of these new features, definitely let us know - we're very open to feedback, either here, on the Moose mailing list, or on #moose-dev on IRC.

Moose 1.18 - the bug fixes continue

Moose 1.18 (and 1.17) are again primarily bug fix releases. In particular, we've killed some bugs that were introduced in 1.15 with the changes to native delegations. If you're using native delegations in your code and you've already installed Moose 1.15 or newer, we strongly encourage you to upgrade.

This release also fixes some random older bugs that have been lingering in rt.cpan for a while.

Finally, this release moves Moose and all of its prereqs from Test::Exception to Test::Fatal. Test::Exception depends on Sub::Uplevel, a module that tends to break with changes in the Perl core. This should make Moose a little more robust against future core changes.