Revision history for Perl extension Moose
+0.09_02
+ * Moose
+ - added prototypes to the exported subs
+
+ * Moose::Role
+ - added prototypes to the exported subs
+
+ * Moose::Util::TypeConstraints
+ - cleaned up prototypes for the subs
+
0.09_01 Fri. May 12, 2006
++ DEVELOPER RELEASE ++
- This release works in combination with
use strict;
use warnings;
-our $VERSION = '0.09_01';
+our $VERSION = '0.09_02';
use Scalar::Util 'blessed', 'reftype';
use Carp 'confess';
my %exports = (
extends => sub {
my $class = $CALLER;
- return subname 'Moose::extends' => sub {
+ return subname 'Moose::extends' => sub ($;@) {
_load_all_classes(@_);
my $meta = $class->meta;
foreach my $super (@_) {
},
with => sub {
my $class = $CALLER;
- return subname 'Moose::with' => sub {
+ return subname 'Moose::with' => sub ($;@) {
my (@roles) = @_;
_load_all_classes(@roles);
($_->can('meta') && $_->meta->isa('Moose::Meta::Role'))
},
has => sub {
my $class = $CALLER;
- return subname 'Moose::has' => sub {
+ return subname 'Moose::has' => sub ($;%) {
my ($name, %options) = @_;
my $meta = $class->meta;
if ($name =~ /^\+(.*)/) {
},
before => sub {
my $class = $CALLER;
- return subname 'Moose::before' => sub {
+ return subname 'Moose::before' => sub (@&) {
my $code = pop @_;
my $meta = $class->meta;
$meta->add_before_method_modifier($_, $code) for @_;
},
after => sub {
my $class = $CALLER;
- return subname 'Moose::after' => sub {
+ return subname 'Moose::after' => sub (@&) {
my $code = pop @_;
my $meta = $class->meta;
$meta->add_after_method_modifier($_, $code) for @_;
},
around => sub {
my $class = $CALLER;
- return subname 'Moose::around' => sub {
+ return subname 'Moose::around' => sub (@&) {
my $code = pop @_;
my $meta = $class->meta;
$meta->add_around_method_modifier($_, $code) for @_;
},
override => sub {
my $class = $CALLER;
- return subname 'Moose::override' => sub {
+ return subname 'Moose::override' => sub ($&) {
my ($name, $method) = @_;
$class->meta->add_override_method_modifier($name => $method);
};
},
augment => sub {
my $class = $CALLER;
- return subname 'Moose::augment' => sub {
+ return subname 'Moose::augment' => sub (@&) {
my ($name, $method) = @_;
$class->meta->add_augment_method_modifier($name => $method);
};
=head1 CAVEAT
-This is an early release of this module, it still needs
-some fine tuning and B<lots> more documentation. I am adopting
-the I<release early and release often> approach with this module,
-so keep an eye on your favorite CPAN mirror!
+Moose is a rapidly maturing module, and is already being used by
+a number of people. It's test suite is growing larger by the day,
+and the docs should soon follow.
+
+This said, Moose is not yet finished, and should still be considered
+to be evolving. Much of the outer API is stable, but the internals
+are still subject to change (although not without serious thought
+given to it).
+
+For more details, please refer to the L<FUTURE PLANS> section of
+this document.
=head1 DESCRIPTION
Perl 5 objects better, but it also provides the power of metaclass
programming.
-=head2 What does Moose stand for??
+=head2 Can I use this in production? Or is this just an experiment?
-Moose doesn't stand for one thing in particular, however, if you
-want, here are a few of my favorites, feel free to contribute
-more :)
+Moose is I<based> on the prototypes and experiments I did for the Perl 6
+meta-model, however Moose is B<NOT> an experiment/prototype, it is
+for B<real>.
-=over 4
+I will be deploying Moose into production environments later this
+year, and I have all intentions of using it as my de-facto class builder
+from now on.
-=item Make Other Object Systems Envious
+=head2 Is Moose just Perl 6 in perl 5?
-=item Makes Object Orientation So Easy
+No. While Moose is very much inspired by Perl 6, it is not. Instead, it
+is an OO system for Perl 5.
-=item Makes Object Orientation Spiffy- Er (sorry ingy)
-
-=item Most Other Object Systems Emasculate
-
-=item My Overcraft Overfilled (with) Some Eels
-
-=item Moose Often Ovulate Sorta Early
-
-=item Many Overloaded Object Systems Exists
-
-=item Moose Offers Often Super Extensions
-
-=item Meta Object Orientation Syntax Extensions
-
-=back
+I built Moose because I was tired or writing the same old boring Perl 5
+OO code, and drooling over Perl 6 OO. So instead of switching to Ruby,
+I wrote Moose :)
=head1 BUILDING CLASSES WITH MOOSE
replace it. This is important to ensure that classes which do not have
superclasses properly inherit from L<Moose::Object>.
-=item B<with ($role)>
+=item B<with (@role)>
-This will apply a given C<$role> to the local class. Role support is
-currently very experimental, see L<Moose::Role> for more details.
+This will apply a given set of C<@role> to the local class. Role support
+is currently under heavy development, see L<Moose::Role> for more details.
=item B<has ($name, %options)>
and can typically be ignored in most cases). You can B<not> have a trigger on
a read-only attribute.
+=item I<handles =E<gt> [ @handles ]>
+
+There is experimental support for attribute delegation using the C<handles>
+option. More docs to come later.
+
=back
=item B<before $name|@names =E<gt> sub { ... }>
=back
+=head1 FUTURE PLANS
+
+Here is just a sampling of the plans we have in store for Moose:
+
+=over 4
+
+=item *
+
+Compiling Moose classes/roles into C<.pmc> files for faster loading and execution.
+
+=item *
+
+Supporting sealed and finalized classes in Moose. This will allow greater control
+of the extensions of frameworks and such.
+
+=back
+
+=head1 MISC.
+
+=head2 What does Moose stand for??
+
+Moose doesn't stand for one thing in particular, however, if you
+want, here are a few of my favorites, feel free to contribute
+more :)
+
+=over 4
+
+=item Make Other Object Systems Envious
+
+=item Makes Object Orientation So Easy
+
+=item Makes Object Orientation Spiffy- Er (sorry ingy)
+
+=item Most Other Object Systems Emasculate
+
+=item My Overcraft Overfilled (with) Some Eels
+
+=item Moose Often Ovulate Sorta Early
+
+=item Many Overloaded Object Systems Exists
+
+=item Moose Offers Often Super Extensions
+
+=item Meta Object Orientation Syntax Extensions
+
+=back
+
=head1 CAVEATS
=over 4
our $VERSION = '0.06';
sub new {
- my $class = shift;
+ my $class = shift;
my %params;
if (scalar @_ == 1) {
(ref($_[0]) eq 'HASH')
use Sub::Exporter;
-our $VERSION = '0.03';
+our $VERSION = '0.04';
use Moose::Meta::Role;
use Moose::Util::TypeConstraints;
},
with => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::with' => sub {
+ return subname 'Moose::Role::with' => sub ($;@) {
my (@roles) = @_;
Moose::_load_all_classes(@roles);
($_->can('meta') && $_->meta->isa('Moose::Meta::Role'))
},
requires => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::requires' => sub {
+ return subname 'Moose::Role::requires' => sub ($;@) {
$meta->add_required_methods(@_);
};
},
excludes => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::excludes' => sub {
+ return subname 'Moose::Role::excludes' => sub ($;@) {
$meta->add_excluded_roles(@_);
};
},
has => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::has' => sub {
+ return subname 'Moose::Role::has' => sub ($;%) {
my ($name, %options) = @_;
$meta->add_attribute($name, %options)
};
},
before => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::before' => sub {
+ return subname 'Moose::Role::before' => sub (@&) {
my $code = pop @_;
$meta->add_before_method_modifier($_, $code) for @_;
};
},
after => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::after' => sub {
+ return subname 'Moose::Role::after' => sub (@&) {
my $code = pop @_;
$meta->add_after_method_modifier($_, $code) for @_;
};
},
around => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::around' => sub {
+ return subname 'Moose::Role::around' => sub (@&) {
my $code = pop @_;
$meta->add_around_method_modifier($_, $code) for @_;
};
},
override => sub {
my $meta = _find_meta();
- return subname 'Moose::Role::override' => sub {
+ return subname 'Moose::Role::override' => sub ($&) {
my ($name, $code) = @_;
$meta->add_override_method_modifier($name, $code);
};
=head1 DESCRIPTION
-This is currently a very early release of Perl 6 style Roles for
-Moose, it is still incomplete, but getting much closer. If you are
-interested in helping move this feature along, please come to
-#moose on irc.perl.org and we can talk.
+Role support in Moose is coming along quite well. It's best documentation
+is still the the test suite, but it is fairly safe to assume Perl 6 style
+behavior, and then either refer to the test suite, or ask questions on
+#moose if something doesn't quite do what you expect. More complete
+documentation is planned and will be included with the next official
+(non-developer) release.
-=head1 CAVEATS
+=head1 EXPORTED FUNCTIONS
+
+Currently Moose::Role supports all of the functions that L<Moose> exports,
+but differs slightly in how some items are handled (see L<CAVEATS> below
+for details).
-Currently, the role support has a few of caveats. They are as follows:
+Moose::Role also offers two role specific keyword exports:
=over 4
-=item *
+=item B<requires (@method_names)>
-At this time classes I<cannot> correctly consume more than one role. The
-role composition process, and it's conflict detection has not been added
-yet. While this should be considered a major feature, it can easily be
-worked around, and in many cases, is not needed at all.
-
-A class can actually consume multiple roles, they are just applied one
-after another in the order you ask for them. This is incorrect behavior,
-the roles should be merged first, and conflicts determined, etc. However,
-if your roles do not have any conflicts, then things will work just
-fine. This actually tends to be quite sufficient for basic roles.
+=item B<excludes (@role_names)>
+
+=back
+
+=head1 CAVEATS
+
+The role support now has only a few caveats. They are as follows:
+
+=over 4
=item *
really make sense for roles). All other Moose keywords will be I<deferred>
so that they can be applied to the consuming class.
+=item *
+
+Role composition does it's best to B<not> be order sensitive when it comes
+to conflict resolution and requirements detection. However, it is order
+sensitive when it comes to method modifiers. All before/around/after modifiers
+are included whenever a role is composed into a class, and then are applied
+in the order the roles are used. This too means that there is no conflict for
+before/around/after modifiers as well.
+
+In most cases, this will be a non issue, however it is something to keep in
+mind when using method modifiers in a role. You should never assume any
+ordering.
+
+=item *
+
+The C<requires> keyword currently only works with actual methods. A method
+modifier (before/around/after and override) will not count as a fufillment
+of the requirement, and neither will an autogenerated accessor for an attribute.
+
+It is likely that the attribute accessors will eventually be allowed to fufill
+those requirements, either that or we will introduce a C<requires_attr> keyword
+of some kind instead. This descision has not yet been finalized.
+
=back
=head1 BUGS
use Carp 'confess';
use Scalar::Util 'blessed';
-our $VERSION = '0.06';
+our $VERSION = '0.07';
use Moose::Meta::TypeConstraint;
use Moose::Meta::TypeCoercion;
-{
- require Sub::Exporter;
-
- my @exports = qw[type subtype as where message coerce from via find_type_constraint enum];
-
- Sub::Exporter->import(
- -setup => {
- exports => \@exports,
- groups => {
- default => [':all']
- }
+use Sub::Exporter
+ -setup => {
+ exports => qw[type subtype as where message coerce from via find_type_constraint enum],
+ groups => {
+ default => [':all']
}
- );
-}
+ }
+);
{
my %TYPES;
- sub find_type_constraint {
+ sub find_type_constraint ($) {
return $TYPES{$_[0]}->[1]
if exists $TYPES{$_[0]};
return;
Data::Dumper::Dumper(\%TYPES);
}
- sub _create_type_constraint {
+ sub _create_type_constraint ($$$;$) {
my ($name, $parent, $check, $message) = @_;
my $pkg_defined_in = scalar(caller(1));
($TYPES{$name}->[0] eq $pkg_defined_in)
return $constraint;
}
- sub _install_type_coercions {
+ sub _install_type_coercions ($$) {
my ($type_name, $coercion_map) = @_;
my $type = find_type_constraint($type_name);
(!$type->has_coercion)
$type->coercion($type_coercion);
}
- sub create_type_constraint_union {
+ sub create_type_constraint_union (@) {
my (@type_constraint_names) = @_;
return Moose::Meta::TypeConstraint->union(
map {
sub subtype ($$;$$) {
unshift @_ => undef if scalar @_ <= 2;
- _create_type_constraint(@_);
+ goto &_create_type_constraint;
}
sub coerce ($@) {
sub via (&) { $_[0] }
sub message (&) { $_[0] }
-sub enum {
+sub enum ($;@) {
my ($type_name, @values) = @_;
+ (scalar @values >= 2)
+ || confess "You must have at least two values to enumerate through";
my $regexp = join '|' => @values;
_create_type_constraint(
$type_name,
use Moose::Util::TypeConstraints;
- type Num => where { Scalar::Util::looks_like_number($_) };
+ type 'Num' => where { Scalar::Util::looks_like_number($_) };
- subtype Natural
- => as Num
+ subtype 'Natural'
+ => as 'Num'
=> where { $_ > 0 };
- subtype NaturalLessThanTen
- => as Natural
+ subtype 'NaturalLessThanTen'
+ => as 'Natural'
=> where { $_ < 10 }
=> message { "This number ($_) is not less than ten!" };
- coerce Num
- => from Str
+ coerce 'Num'
+ => from 'Str'
=> via { 0+$_ };
- enum RGBColors => qw(red green blue);
+ enum 'RGBColors' => qw(red green blue);
=head1 DESCRIPTION
This is simply a means of creating small constraint functions which
can be used to simplify your own type-checking code.
+=head2 Slightly Less Important Caveat
+
+It is almost always a good idea to quote your type and subtype names.
+This is to prevent perl from trying to create the call as an indirect
+object call. This issue only seems to come up when you have a subtype
+the same name as a valid class, but when the issue does arise it tends
+to be quite annoying to debug.
+
+So for instance, this:
+
+ subtype DateTime => as Object => where { $_->isa('DateTime') };
+
+will I<Just Work>, while this:
+
+ use DateTime;
+ subtype DateTime => as Object => where { $_->isa('DateTime') };
+
+will fail silently and cause many headaches. The simple way to solve
+this, as well as future proof your subtypes from classes which have
+yet to have been created yet, is to simply do this:
+
+ use DateTime;
+ subtype 'DateTime' => as Object => where { $_->isa('DateTime') };
+
=head2 Default Type Constraints
This module also provides a simple hierarchy for Perl 5 types, this
Role
Suggestions for improvement are welcome.
+
+B<NOTE:> The C<Undef> type constraint does not work correctly
+in every occasion, please use it sparringly.
=head1 FUNCTIONS
=item B<enum ($name, @values)>
+This will create a basic subtype for a given set of strings.
+The resulting constraint will be a subtype of C<Str> and
+will match any of the items in C<@values>. See the L<SYNOPSIS>
+for a simple example.
+
+B<NOTE:> This is not a true proper enum type, it is simple
+a convient constraint builder.
+
=item B<as>
This is just sugar for the type constraint construction syntax.