Things I've learned by Moosifying classes over the past few days. In no particular order.
Moose is cool.
But it's too easy to go overboard and try to use all of it at once.
Type constraints are very useful, if nothing else because of the documentation value, e.g.
has 'rex_skip_source_file' => ( is => 'rw', isa => 'ArrayRef[RegexpRef]', default => sub { [] }, );The default of ''is => "ro"'' seems badly chosen. Having ''is => "rw"'' everywhere seriously adds clutter. From what I gather it's from Perl 6, and the little Perl 6 code I've seen leaves the same impression. I guess the argument is "public accessors are bad so it should hurt to use them". But that argument doesn't hold water, because this is also how you declare private attributes. So either way, most of your attribute declarations will have "rw". Not very optimized for the common case.
has is_publication_outlet => (is => "rw", isa => "Int");
isa => "Maybe[Str]"To override the default for an attribute in a subclass without having to retype the entire declaration you prepend a plus:
has "+is_persistable" => (default => 1);This visual distinction feels very right and makes it obvious it is overridden.
Many attributes in a compact layout become visually disturbing. Aligning things here is a must for readability. Apparently Vim has some kind of magic I'm envious of.
No, that's just applying my default
First off, thanks for the nice review, it is good to get feedback from new Moose users. The #moose echo chamber on IRC is obviously not so helpful in this regard.
The default of ''is => "ro"' is badly chosen
...
Actually the default is to not create any accessors at all. While it might seem useless, it is a perfectly valid use case, take this example for instance:
has 'some_flag' => (
predicate => 'is_some_flag_set'
);
This will create a predicate method for checking if the flag is set, but no accessors for it. If there was a default, then you would need to supply a way of overriding the default here. And of course you can also set the reader/writer stuff yourself like:
has 'thing' => (
isa => 'Int',
reader => 'get_thing',
writer => '_set_thing',
);
Which if there was a default is => 'ro' already would require Moose to know when the default is overridden, etc. So while is does seem like a good idea to default to 'rw' after you have written your 20th (is => 'rw'), it would either reduce the flexibility or add internal complexity.
Many attributes in a compact layout become visually disturbing. Aligning things here is a must for readability. Apparently Vim has some kind of magic I'm envious of. A very simple split-on-non-string-whitespace-and-render-in-columns would work here.
If you are using TextMate you might want to look at the Moose Bundle it provides a lot of nice automation for writing Moose classes (if you aren't using TextMate you might want to give it a look too, it is an excellent editor). One of these days I will do a screencast for it.
Bool seems weird and doesn't play well with Perl's idea of true / false.
Could you elaborate on this please? The Bool type is meant to map to how Perl handles boolean values, so it accepts undef, '', 1 and 0. It differs from Perl in that it wont accept an arbitrary value and treat it as true.
Roles are nice but the keywod "with MyRole" isn't the same as Perl 6' "does MyRole".
The reason for this is because we needed to allow for $object->does('Role')
, and overloading 'does' seemed like a recipe for disaster. It is the same as why we went with extends 'My::Superclass'
and not isa 'My::Superclass'
.
And lastly, the docs, they need some help we know. Contributions are always welcome in that regard and when $work and $real_life slow down enough I am planning to write some more introductory pieces. In the meantime the talks and articles listed on the website provide a pretty good (although kinda disorganized) addition to the POD docs.
- Stevan
Re:Thanks.
sigzero on 2008-07-08T14:51:35
Regarding "docs". Do you know of a book that may be in the works? It seems to me that Moose is such a good thing for Perl OO that it would be a good thing to have a book out there as well.
Re:Book in the works
Stevan on 2008-07-08T18:16:47
Nope, not that I am involved in or have been approached about. I agree though, would be a good idea.
- Stevan
Re:Thanks.
jplindstrom on 2008-07-08T17:14:34
It differs from Perl in that it wont accept an arbitrary value and treat it as true.
That was what I was referring to. Maybe if it's advertised as these-are-the-Perl-types kind of type constraint it should actually conform to the Perl true/false idea, and if you want to stricten it up to only support 1/0/undef you use a different one (Bool vs Boolean) ?
Anyway, it surprised me when using it, that's all.
/J Re:Thanks.
Stevan on 2008-07-08T18:27:56
I think perhaps you are mistaking a "value" for the "value of an expression". When Perl sees
if (@foo) {
... } it evaluates
@foo
as an expression, and in that context it returns true. If I were to invent a "boolean" built in similar to the "scalar" built in, which forced "boolean context", then the above code would desugar intoif (boolean(@foo)) {
... } Just as
my $foo = @foo;
desugars into
my $foo = scalar @foo;
Now in the context of Moose, when you assign a value to an accessor it does not impose the "boolean context" on it, so it only sees a value, and therefore does not pass the type constraint.
- Stevan