X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose.pm;h=c7ca1a840ae89eb7a371c4afe9b19b746b2c8eff;hb=b8926b8c7d85fc00b3b680d2e2d20878b320f772;hp=3ec025aa1f4bbfbb8bf7c6e9c8ecfdb93717d067;hpb=c2922d6931cf933d48203d8d972e9605bb66dd35;p=gitmo%2FMoose.git diff --git a/lib/Moose.pm b/lib/Moose.pm index 3ec025a..c7ca1a8 100644 --- a/lib/Moose.pm +++ b/lib/Moose.pm @@ -4,20 +4,18 @@ package Moose; use strict; use warnings; -our $VERSION = '0.41'; +our $VERSION = '0.45'; our $AUTHORITY = 'cpan:STEVAN'; use Scalar::Util 'blessed', 'reftype'; -use Carp 'confess'; -use Sub::Name 'subname'; +use Carp 'confess', 'croak', 'cluck'; use Sub::Exporter; -use Class::MOP; +use Class::MOP 0.56; use Moose::Meta::Class; use Moose::Meta::TypeConstraint; -use Moose::Meta::TypeConstraint::Class; use Moose::Meta::TypeCoercion; use Moose::Meta::Attribute; use Moose::Meta::Instance; @@ -80,8 +78,8 @@ use Moose::Util (); my %exports = ( extends => sub { my $class = $CALLER; - return subname 'Moose::extends' => sub (@) { - confess "Must derive at least one class" unless @_; + return Class::MOP::subname('Moose::extends' => sub (@) { + croak "Must derive at least one class" unless @_; my @supers = @_; foreach my $super (@supers) { @@ -93,85 +91,83 @@ use Moose::Util (); # of sync when the classes are being built my $meta = $class->meta->_fix_metaclass_incompatability(@supers); $meta->superclasses(@supers); - }; + }); }, with => sub { my $class = $CALLER; - return subname 'Moose::with' => sub (@) { + return Class::MOP::subname('Moose::with' => sub (@) { Moose::Util::apply_all_roles($class->meta, @_) - }; + }); }, has => sub { my $class = $CALLER; - return subname 'Moose::has' => sub ($;%) { + return Class::MOP::subname('Moose::has' => sub ($;%) { my $name = shift; - die 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1; + croak 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1; my %options = @_; my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ]; $class->meta->add_attribute( $_, %options ) for @$attrs; - }; + }); }, before => sub { my $class = $CALLER; - return subname 'Moose::before' => sub (@&) { - my $code = pop @_; - my $meta = $class->meta; - $meta->add_before_method_modifier( $_, $code ) for @_; - }; + return Class::MOP::subname('Moose::before' => sub (@&) { + Moose::Util::add_method_modifier($class, 'before', \@_); + }); }, after => sub { my $class = $CALLER; - return subname 'Moose::after' => sub (@&) { - my $code = pop @_; - my $meta = $class->meta; - $meta->add_after_method_modifier( $_, $code ) for @_; - }; + return Class::MOP::subname('Moose::after' => sub (@&) { + Moose::Util::add_method_modifier($class, 'after', \@_); + }); }, around => sub { my $class = $CALLER; - return subname 'Moose::around' => sub (@&) { - my $code = pop @_; - my $meta = $class->meta; - $meta->add_around_method_modifier( $_, $code ) for @_; - }; + return Class::MOP::subname('Moose::around' => sub (@&) { + Moose::Util::add_method_modifier($class, 'around', \@_); + }); }, super => sub { - { - our %SUPER_SLOT; - no strict 'refs'; - $SUPER_SLOT{$CALLER} = \*{"${CALLER}::super"}; - } - return subname 'Moose::super' => sub { }; + return Class::MOP::subname('Moose::super' => sub { + return unless our $SUPER_BODY; $SUPER_BODY->(our @SUPER_ARGS) + }); }, override => sub { my $class = $CALLER; - return subname 'Moose::override' => sub ($&) { + return Class::MOP::subname('Moose::override' => sub ($&) { my ( $name, $method ) = @_; $class->meta->add_override_method_modifier( $name => $method ); - }; + }); }, inner => sub { - { - our %INNER_SLOT; - no strict 'refs'; - $INNER_SLOT{$CALLER} = \*{"${CALLER}::inner"}; - } - return subname 'Moose::inner' => sub { }; + return Class::MOP::subname('Moose::inner' => sub { + my $pkg = caller(); + our ( %INNER_BODY, %INNER_ARGS ); + + if ( my $body = $INNER_BODY{$pkg} ) { + my @args = @{ $INNER_ARGS{$pkg} }; + local $INNER_ARGS{$pkg}; + local $INNER_BODY{$pkg}; + return $body->(@args); + } else { + return; + } + }); }, augment => sub { my $class = $CALLER; - return subname 'Moose::augment' => sub (@&) { + return Class::MOP::subname('Moose::augment' => sub (@&) { my ( $name, $method ) = @_; $class->meta->add_augment_method_modifier( $name => $method ); - }; + }); }, make_immutable => sub { my $class = $CALLER; - return subname 'Moose::make_immutable' => sub { - warn "The make_immutable keyword has been deprecated, " . - "please go back to __PACKAGE__->meta->make_immutable\n"; + return Class::MOP::subname('Moose::make_immutable' => sub { + cluck "The make_immutable keyword has been deprecated, " . + "please go back to __PACKAGE__->meta->make_immutable\n"; $class->meta->make_immutable(@_); - }; + }); }, confess => sub { return \&Carp::confess; @@ -231,7 +227,6 @@ use Moose::Util (); # make sure it is from Moose my ($pkg_name) = Class::MOP::get_code_info($keyword); - next if $@; next if $pkg_name ne 'Moose'; # and if it is from Moose then undef the slot @@ -309,62 +304,22 @@ Moose - A postmodern object system for Perl 5 Moose is an extension of the Perl 5 object system. -=head2 Another object system!?!? - -Yes, I know there has been an explosion recently of new ways to -build object's in Perl 5, most of them based on inside-out objects -and other such things. Moose is different because it is not a new -object system for Perl 5, but instead an extension of the existing -object system. - -Moose is built on top of L, which is a metaclass system -for Perl 5. This means that Moose not only makes building normal -Perl 5 objects better, but it also provides the power of metaclass -programming. - -=head2 Is this for real? Or is this just an experiment? - -Moose is I on the prototypes and experiments I did for the Perl 6 -meta-model. However, Moose is B an experiment/prototype; it is for B. - -=head2 Is this ready for use in production? - -Yes, I believe that it is. - -Moose has been used successfully in production environemnts by several people -and companies (including the one I work for). There are Moose applications -which have been in production with little or no issue now for well over a year. -I consider it highly stable and we are commited to keeping it stable. - -Of course, in the end, you need to make this call yourself. If you have -any questions or concerns, please feel free to email me, or even the list -or just stop by #moose and ask away. - -=head2 Is Moose just Perl 6 in Perl 5? - -No. While Moose is very much inspired by Perl 6, it is not itself Perl 6. -Instead, it is an OO system for Perl 5. I built Moose because I was tired of -writing the same old boring Perl 5 OO code, and drooling over Perl 6 OO. So -instead of switching to Ruby, I wrote Moose :) - -=head2 Wait, I modern, I thought it was just I? - -So I was reading Larry Wall's talk from the 1999 Linux World entitled -"Perl, the first postmodern computer language" in which he talks about how -he picked the features for Perl because he thought they were cool and he -threw out the ones that he thought sucked. This got me thinking about how -we have done the same thing in Moose. For Moose, we have "borrowed" features -from Perl 6, CLOS (LISP), Smalltalk, Java, BETA, OCaml, Ruby and more, and -the bits we didn't like (cause they sucked) we tossed aside. So for this -reason (and a few others) I have re-dubbed Moose a I object system. +The main goal of Moose is to make Perl 5 Object Oriented programming +easier, more consistent and less tedious. With Moose you can to think +more about what you want to do and less about the mechanics of OOP. -Nuff Said. +Additionally, Moose is built on top of L, which is a +metaclass system for Perl 5. This means that Moose not only makes +building normal Perl 5 objects better, but it provides the power of +metaclass programming as well. =head2 Moose Extensions The L namespace is the official place to find Moose extensions. There are a number of these modules out on CPAN right now the best way to -find them is to search for MooseX:: on search.cpan.org. +find them is to search for MooseX:: on search.cpan.org or to look at the +latest version of L which aims to keep an up to date, easily +installable list of these extensions. =head1 BUILDING CLASSES WITH MOOSE @@ -381,11 +336,10 @@ L) this includes properly initializing all instance slots, setting defaults where appropriate, and performing any type constraint checking or coercion. -=head1 EXPORTED FUNCTIONS +=head1 PROVIDED METHODS -Moose will export a number of functions into the class's namespace which -may then be used to set up the class. These functions all work directly -on the current class. +Moose provides a number of methods to all your classes, mostly through the +inheritance of L. There is however, one exception. =over 4 @@ -393,6 +347,16 @@ on the current class. This is a method which provides access to the current class's metaclass. +=back + +=head1 EXPORTED FUNCTIONS + +Moose will export a number of functions into the class's namespace which +may then be used to set up the class. These functions all work directly +on the current class. + +=over 4 + =item B This function will set the superclass(es) for the current class. @@ -404,8 +368,7 @@ superclasses still properly inherit from L. =item B -This will apply a given set of C<@roles> to the local class. Role support -is currently under heavy development; see L for more details. +This will apply a given set of C<@roles> to the local class. =item B %options> @@ -424,7 +387,8 @@ accessor respectively, using the same name as the C<$name> of the attribute. If you need more control over how your accessors are named, you can use the I, I and I options inherited from -L. +L, however if you use those, you won't need the I +option. =item I $type_name> @@ -469,22 +433,6 @@ If an attribute is marked as lazy it B have a default supplied. This tells the accessor whether to automatically dereference the value returned. This is only legal if your C option is either C or C. -=item I $metaclass_name> - -This tells the class to use a custom attribute metaclass for this particular -attribute. Custom attribute metaclasses are useful for extending the -capabilities of the I keyword: they are the simplest way to extend the MOP, -but they are still a fairly advanced topic and too much to cover here. I will -try and write a recipe on them soon. - -The default behavior here is to just load C<$metaclass_name>; however, we also -have a way to alias to a shorter name. This will first look to see if -B exists. If it does, Moose -will then check to see if that has the method C, which -should return the actual name of the custom attribute metaclass. If there is no -C method, it will fall back to using -B as the metaclass name. - =item I $code> The I option is a CODE reference which will be called after the value of @@ -499,10 +447,6 @@ The I option provides Moose classes with automated delegation features. This is a pretty complex and powerful option. It accepts many different option formats, each with its own benefits and drawbacks. -B This feature is no longer experimental, but it may still have subtle -bugs lurking in the deeper corners. If you think you have found a bug, you -probably have, so please report it to me right away. - B The class being delegated to does not need to be a Moose based class, which is why this feature is especially useful when wrapping non-Moose classes. @@ -602,6 +546,37 @@ a HASH ref) of the methods you want mapped. =back +=item I $metaclass_name> + +This tells the class to use a custom attribute metaclass for this particular +attribute. Custom attribute metaclasses are useful for extending the +capabilities of the I keyword: they are the simplest way to extend the MOP, +but they are still a fairly advanced topic and too much to cover here, see +L for more information. + +The default behavior here is to just load C<$metaclass_name>; however, we also +have a way to alias to a shorter name. This will first look to see if +B exists. If it does, Moose +will then check to see if that has the method C, which +should return the actual name of the custom attribute metaclass. If there is no +C method, it will fall back to using +B as the metaclass name. + +=item I [ @role_names ]> + +This tells Moose to take the list of C<@role_names> and apply them to the +attribute meta-object. This is very similar to the I option, but +allows you to use more than one extension at a time. This too is an advanced +topic, we don't yet have a cookbook for it though. + +As with I, the default behavior is to just load C<$role_name>; however, +we also have a way to alias to a shorter name. This will first look to see if +B exists. If it does, Moose +will then check to see if that has the method C, which +should return the actual name of the custom attribute trait. If there is no +C method, it will fall back to using +B as the trait name. + =back =item B %options> @@ -680,8 +655,12 @@ Change if the attribute lazily initializes the slot. =item I -You I allowed to change the type, B the new type is a -subtype of the old type. +You I allowed to change the type without restriction. + +It is recommended that you use this freedom with caution. We used to +only allow for extension only if the type was a subtype of the parent's +type, but we felt that was too restrictive and is better left as a +policy descision. =item I @@ -693,6 +672,17 @@ allowed to I one. You are allowed to B a new C definition, but you are B allowed to I one. +=item I + +You are allowed to B a new C definition, but you are +B allowed to I one. + +=item I + +You are allowed to B additional traits to the C definition. +These traits will be composed into the attribute, but pre-existing traits +B overridden, or removed. + =back =item B sub { ... }> @@ -724,18 +714,18 @@ method call and the C pseudo-package; it is really your choice. The keyword C, much like C, is a no-op outside of the context of an C method. You can think of C as being the inverse of C; the details of how C and C work is best described in -the L. +the L. =item B An C method, is a way of explicitly saying "I am augmenting this method from my superclass". Once again, the details of how C and -C work is best described in the L. +C work is best described in the L. =item B This is the C function, and exported here because I use it -all the time. This feature may change in the future, so you have been warned. +all the time. =item B @@ -825,6 +815,75 @@ two features separate (yet interoperable) actually makes them easy to use, since their behavior is then easier to predict. Time will tell whether I am right or not (UPDATE: so far so good). +=item * + +It is important to note that we currently have no simple way of combining +multiple extended versions of Moose (see L above), +and that in many cases they will conflict with one another. We are working on +developing a way around this issue, but in the meantime, you have been warned. + +=back + +=head1 JUSTIFICATION + +In case you are still asking yourself "Why do I need this?", then this +section is for you. This used to be part of the main DESCRIPTION, but +I think Moose no longer actually needs justification, so it is included +(read: buried) here for those who are still not convinced. + +=over 4 + +=item Another object system!?!? + +Yes, I know there has been an explosion recently of new ways to +build objects in Perl 5, most of them based on inside-out objects +and other such things. Moose is different because it is not a new +object system for Perl 5, but instead an extension of the existing +object system. + +Moose is built on top of L, which is a metaclass system +for Perl 5. This means that Moose not only makes building normal +Perl 5 objects better, but it also provides the power of metaclass +programming. + +=item Is this for real? Or is this just an experiment? + +Moose is I on the prototypes and experiments I did for the Perl 6 +meta-model. However, Moose is B an experiment/prototype; it is for B. + +=item Is this ready for use in production? + +Yes, I believe that it is. + +Moose has been used successfully in production environemnts by several people +and companies (including the one I work for). There are Moose applications +which have been in production with little or no issue now for well over two years. +I consider it highly stable and we are commited to keeping it stable. + +Of course, in the end, you need to make this call yourself. If you have +any questions or concerns, please feel free to email me, or even the list +or just stop by #moose and ask away. + +=item Is Moose just Perl 6 in Perl 5? + +No. While Moose is very much inspired by Perl 6, it is not itself Perl 6. +Instead, it is an OO system for Perl 5. I built Moose because I was tired of +writing the same old boring Perl 5 OO code, and drooling over Perl 6 OO. So +instead of switching to Ruby, I wrote Moose :) + +=item Wait, I modern, I thought it was just I? + +So I was reading Larry Wall's talk from the 1999 Linux World entitled +"Perl, the first postmodern computer language" in which he talks about how +he picked the features for Perl because he thought they were cool and he +threw out the ones that he thought sucked. This got me thinking about how +we have done the same thing in Moose. For Moose, we have "borrowed" features +from Perl 6, CLOS (LISP), Smalltalk, Java, BETA, OCaml, Ruby and more, and +the bits we didn't like (cause they sucked) we tossed aside. So for this +reason (and a few others) I have re-dubbed Moose a I object system. + +Nuff Said. + =back =head1 ACKNOWLEDGEMENTS @@ -841,7 +900,7 @@ and it certainly wouldn't have this name ;P =item The basis of the TypeContraints module was Rob Kinyon's idea originally, I just ran with it. -=item Thanks to mst & chansen and the whole #moose poose for all the +=item Thanks to mst & chansen and the whole #moose posse for all the early ideas/feature-requests/encouragement/bug-finding. =item Thanks to David "Theory" Wheeler for meta-discussions and spelling fixes. @@ -864,12 +923,23 @@ technologies. =item The Moose mailing list - moose@perl.org -=item Moose stats on ohloh.net - L +=item Moose stats on ohloh.net - L =item Several Moose extension modules in the L namespace. =back +=head2 Books + +=over 4 + +=item The Art of the MetaObject Protocol + +I mention this in the L docs too, this book was critical in +the development of both modules and is highly recommended. + +=back + =head2 Papers =over 4