Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of Stevan (6065)

Friday March 14, 2008
04:25 PM

Task::Moose released

I have just uploaded Task::Moose which provides a simple way to install Moose and (optionally) install many useful extensions as well. This is not only a handy way to install Moose, but it is a nice way to keep a running list of the latest extensions and add-ons.

I am also quite proud of the fact that Moose now has 100% chance of installing smoothly on Perl 5.8.8 and we are in the high 90%s for Perl 5.10. It is a common myth that Moose is full of magic and has lots of heavy dependencies, but the reality is we use suprisingly little magic and have 9 non-core dependencies (yes, there is some XS in there, but hey, you want it fast right?).

- Stevan

Monday January 21, 2008
11:03 PM

New Moose Features in 0.34

The latest release of Moose (0.34) brings with it some very nice features as well as a major re-factoring of the role system (I am finally happy with the design now too) and a re-factoring of the parameterized types. While most of the information on the new features is in the Changes file, I figured that they are cool enough to be blog-worthy too, so here goes.

New Maybe[`a] parameterized type

The handling of parameterized types has been re-factored so that it is now possible to add new parameterized types without needing them to be based off the ArrayRef or HashRef type (no syntactic sugar yet though). As a demonstration of this, and because it's just a useful thing anyway I have added the Maybe[`a] type. This type basically means "maybe there will be a value, and if there is, it will be of type `a", users of Haskell will be familiar with this (as will O'Caml users, it is similar to the 'option' type). Here is an example of the usage:

package Person;
use Moose;

has 'first_name'     => (is => 'rw', isa => 'Str');
has 'last_name'      => (is => 'rw', isa => 'Str');
has 'middle_initial' => (is => 'rw', isa => 'Maybe[Str]');

The 'middle_initial' attribute now allows either a string or an undefined value to be stored.

Role method exclusion and aliasing

Role composition follows a strictly defined set of rules, this is one of the benefits of roles over your basic mix-ins or multiple inheritance. But sometimes, you want to subvert those rules and have more control over the composition process. The original Traits paper (on which Roles are based) included both 'exclusion' and 'aliasing' operations as a way of modifying the composition process. I included these features when I originally wrote Class::Trait, but since @larry had not added them into Perl 6 I hadn't included support in Moose. Now after several months of using Roles I now see the original wisdom of the Traits paper authors and these features are now available in Moose. Here are some examples of usage:

Lets create an Equality role, which provides the mechanism for determining, well, equality.

package Equality;
use Moose::Role;

requires 'equal';
sub not_equal { not((shift)->equal(@_)) }

Now lets define two more roles which do the Equality role, first a 'HasColor' role:

package HasColor;
use Moose::Role;

with 'Equality';

# create an attribute to hold RGB values
has 'rgb' => (is => 'rw', isa => 'ArrayRef[Int]');

sub equal { ... code to compare RBG values ... }

And now a 'HasCoordinate' role

package HasCoordinate;
use Moose::Role;

with 'Equality';

# create an attribute to hold x/y values
has 'coord' => (is => 'rw', isa => 'ArrayRef[Int]');

sub equal { ... code to compare x/y values ... }

Now if my 'Pixel' class wanted to use both the 'HasColor' and 'HasCoordinate' roles, ...

package Pixel;
use Moose;

with 'HasColor', 'HasCoordinate';

I would have a problem because their 'equal' methods would conflict. The conflict means that the 'Pixel' class must then implement an 'equal' method of it's own. I could implement it like so:

sub equal {
    my ($self, $other) = @_;
    $self->HasColor::equal($other) &&
    $self->HasCoordinate::equal($other);
}

but the hardcoding of role names like this is a design smell IMO. We also have lost color and coordinate comparison abilities in our 'Pixel' class. Here is a different approach using exclusion and aliasing to provide (IMO) a much superior solution.

package Pixel;
use Moose;

with 'HasColor' => {
        excludes => 'equal',
        alias    => { equal => 'color_equal' }
     },
     'HasCoordinate' => {
        excludes => 'equal',
        alias    => { equal => 'coord_equal' }
     };

sub equal {
    my ($self, $other) = @_;
    $self->color_equal($other) && $self->coord_equal($other);
}

The above code now removes the conflict between the 'equal' methods, but aliases them so that the features are not lost and finally implements equals in terms of them.

Of course this example is a little on the contrived side, but you get the point. Anyone who has messed around with roles enough will surely rejoice at this new feature addition.

Attribute Metaclass traits

We already have support for custom attribute metaclasses and this feature is used in a number of modules, MooseX::Getopt, MooseX::Storage and MooseX::AttributeHelpers to name a few. It allows you to extend the features of Moose attributes to provide additional functionality within the same Moose framework. The one problem with this feature has always been that it is very difficult to combine these extensions and use more than one at a time. Here is a (very contrived) example of how this feature will be useful.

package My::App;
use Moose;
use MooseX::Storage;
use MooseX::Getopt;

has 'some_thing' => (
    traits => [qw/DoNotSerialize NoGetopt/],
    is     => 'rw',
    isa    => 'ArrayRef[Big::Heavy::Things]',
    # ...
);

Currently MooseX::Storage provides a DoNotSerialize metaclass which lets the MooseX::Storage engine know to skip that attribute when serializing. This is fine, until you need to also use the MooseX::Getopt provided NoGetopt metaclass (which, yes you guessed it, tells MooseX::Getopt that this is not a command line parameter). I will soon be releasing versions of those two modules which will make the above example work, allowing you to easily combine both non-serialization with non-getopt-parsing. (Sorry, that was the best example I could come up with right now, we are working on a possible cookbook entry so if this interests you keep you eyes out).

And lastly ...

And lastly, in addition to all this new functionality, I would like to announce the upcoming release of MooseX::Compile 0.01 (possibly by tomorrow morning). MooseX::Compile is a project here at $work which takes all the stored meta-information of a Moose class and compiles a .pmc file which defers loading the bulk of the Moose infrastructure and caches the already computed metaclasses. It is still in it's very early stages, and only supports a subset of Moose, but results are extremely promising.

- Stevan

Wednesday January 16, 2008
10:49 AM

All I want for Christmas is Perl 5.12

Don't get me wrong, I love Perl 6, I spend most of my spare time maintaining a port of its object system in Perl 5. But lets be realistic, if Perl 6.0.0 comes out in Christmas 200x I will not be rushing to load it onto my production boxes and stake my livelihood on it. This is not beacuse I have no faith in the Perl 6 team, quite the contrary, just that it is an untested language (no, not unit tests, and audreyt deploying Pugs in prod doesn't count) and an untested platform (Parrot). Now Christmas 200(x + 1), thats a different story.

So, with that disclaimer out of the way, I have to say that I am really excited about the developments taking place on p5p regarding the Perl 5.12 features. Perl 5.10 is already got some really nice bits and 5.12 will surely introduce even more, bringing us even closer to the Perl 6 goodness. Yes, yes, even with its infamous jenga internals Perl 5 is still rock solid (it has never done me wrong), and with 16,000,000+ lines of nightmare legacy code (a.k.a. - CPAN) I know it's well tested.

- Stevan

Friday December 14, 2007
05:10 PM

Moose 2x Speed-Up

One of the biggest complaints/problems with Moose has always been it's compile time cost. Well with the newest release of Moose (0.33) and Class::MOP (0.49) we have made a major step towards reducing that. With judicious use of XS (konobi++ for that) and some caching in key parts of Class::MOP we have managed to cut Moose load time almost in half, here are the stats from my machine (MacBook Pro w/ 2.4 GHz Intel Core 2 Duo).

Moose 0.32 & Class::MOP 0.48 => 0.46 real 0.43 user 0.02 sys
Moose 0.33 & Class::MOP 0.49 => 0.27 real 0.22 user 0.02 sys

This change also brings allowed us to take advantage of some 5.10 specific improvements as well. In 5.8.* we use the PL_sub_generation interpreter global to determine when to invalidate our method cache, which was one of the big parts of the speed win. In 5.8.* this is incremented every time a package is changed, which means we were probably invalidating our cache even when we didn't need to. Now in 5.10 we are using the mro::get_pkg_gen function, which provides the same feature but increments on a per-package basis, which means less incorrect cache invalidation.

All in all, not bad for a few hours of work by the folks on #moose.

- Stevan

NOTE: I got my stats wrong in the ChangeLogs, I called it a ~45% speed increase, but it is really 45% less slow.

Thursday August 30, 2007
05:03 AM

YAPC::EU Moose slides uploaded

I have just uploaded the slides from the Moose talk I gave yesterday at YAPC::EU. They are a revised version of a talk I gave at the Perl Seminiar NY earlier this year, I think this version flows a little better and I was pretty happy with how the talk went. I was hoping to include more information about roles into this talk, but there was not time. Maybe the next talk.

- Stevan

Tuesday July 17, 2007
08:40 AM

Class::MOP/Moose now works in 5.9.5

Finally, thanks to mst (of DBIx::Class fame) we have a new version of Class::MOP which passes all tests cleanly in perl 5.9.5 (all while retaining backwards compat too). This was after a few attempts at fixing and then a couple attempts at just silencing the offending test (it really was just an edge case which did not affect the actual operation of the module), we now actually have a properly passing version. Horray for mst!

This now paves the way for experimenting with the new features of 5.9.5 in Class::MOP and Moose themselves, specifically the mro pragma, the given/when construct and smart matching. I plan on using my YAPC::EU time away from $work to start an experimental branch. Should be fun!

- Stevan

Tuesday April 03, 2007
03:24 PM

Moose is turning 1yr old soon

About a year ago I released the first version of Moose to CPAN, and since then we have used it extensively in a number of projects. And now with 3 apps which have been in production for between 6 and 9 months without issue, and positive reports from several other developers who have had similar experiences, I am happy to announce that Moose is pretty much ready for general use (i.e. - not scary anymore).

Huh, what,.. Moose??,.. what are you talking about??

For those who don't know, Moose is a complete modern object framework for Perl based on the work done by myself and others in the Pugs and Perl 6 projects. It does not claim to be Perl 6, but instead brings a Perl 6 like object system to Perl 5. This means it is built from the groud up to play nicely with existing Perl 5 objects and object systems.

So where can I get more information?

Well, lots of places actually. A good place to start is the Moose::Cookbook. Additional resources can be found from here as well.

There is also an ever growing set of MooseX:: plugins being developed to extend and enhance Moose (some are still under development here, but soon to be released).

I am also going to be giving a talk at the upcoming Perl NY Seminar on April 17th (I will post more details on this later), and (if they get accepted) hopefully at least one talk at this years YAPC::EU.

Does this mean 1.0 is coming out soon?

Nah, I decided 1.0 was just a number, and a silly one at that. The latest stable (0.18) should be thought of as "1.0" in spirit, just not in name.

-Stevan

Thursday September 14, 2006
02:22 PM

Class::MOP browser - Now Smalltalk ain't got nothin' on us

I recently hacked together a very basic Smalltalk-esque class browser for Class::MOP. This is really just a basic proof of concept, and it was pretty simple to build, in fact, it is pretty much all TT code. (My CSS and HTML skills are sorely lacking, so my apologies if it looks really bad).

Of course being a proof of concept, it has many caveats. To start with, it needs the bleeding edge (svn) version of Class::MOP. It does not yet work well with Moose either (this is because the latest Moose is not yet synced up with the bleeding edge Class::MOP).

But it is not all bad news :) it does some really cool stuff as well. To start with, it is not just restircted to Class::MOP and Moose classes. Because Class::MOP is meant to also be able to introspect vanilla Perl OO, it can be used to browse those classes as well. And if you are using Moose or Class::MOP, the browser simply loads all the metaclasses in Class::MOP's metaclass cache, so as long as you load your classes, they will appear in the browser.

The eventual goal is to make this into a more full featured class browser, with full support for both Moose and non-Moose classes & possibly also including documentation (parsed from the POD). But anyway, enough babbling, back to $work for now.

- Stevan

Thursday August 17, 2006
02:38 PM

Moose::Autobox - Ruby ain't got nothin on us

I have just released the newest version of Moose::Autobox (0.03 to be exact), which adds a few nice improvements. First is that you no longer need to use autobox, just use Moose::Autobox will do. Next is the ability to mixin new roles at runtime, which makes neat things like this Ruby ActiveSupport style date trick very easy to accomplish.

Moose::Autobox->mixin_additional_role(SCALAR => 'Units::Time');

print 2->days->ago->as_string;
print 3->weeks->from_now->as_string;

See the Moose::Autobox examples directory for more details.

The next new toy (and my personal favorite) is the Y combinator is now available for CODE references. For those who are not familiar the Y combinator is a fixed-point combinator which can be used to turn an unnamed or anonymous subroutine into a recursive one. It does this through a series of complex tricks which are beyond the scope of this post, so it is probably best to just show a code example.

my $factorial = sub {
    my $f = shift;
    sub {
        my $n = shift;
        return 1 if $n < 2;
        return $n * $f->($n - 1);
    }
}->y;

$factorial->(10) # returns 3628800

This is now much shorter then the ruby version (and cleaner to IMHO).

Now all we need is a dashingly handsome spokesmodel and Perl can be the new Ruby ;)

- Stevan

Friday August 11, 2006
01:24 PM

Flexing Moose

I tried to build Moose to be a very flexible system. Pretty much all it's behaviors can be customized by overriding/extending it's default metaclasses. However, metaclass hacking can be both scary and very tricky, which is where Moose::Policy comes in.

One of the most common complaints I have heard about Moose is that it does not support { get, set }_foo (Perl Best Practicies approved) style accessors out of the box. Of course, this is easily done with a custom attribute metaclass, but that's not what people tend to want to hear. Now, with Moose::Policy it is as simple as this:

package Point;
use Moose::Policy 'Moose::Policy::FollowPBP';
use Moose;

has 'x' => (is => 'rw', isa => 'Int');
has 'y' => (is => 'rw', isa => 'Int');

Now Point has get_x, get_y, set_x and set_y methods generated for it's accessors.

Moose::Policy is basically a way to manage a set of metaclass customizations on a class-per-class basis without having to deal with those metaclasses directly. It also makes it pretty easy to package up these customizations for distribution with your project since a Policy is just another Perl 5 package file (see Moose::Policy for some examples).

The future plans for Moose::Policy include creating a number of roles which can be composed together to create custom policies without even having to touch metaclasses at all.

So, if you have looked at Moose and thought to yourself, "I would use it if only it had x feature", then let me know. Chances are that feature can be made into a Moose::Policy and we can add it to the distribution.

- Stevan