some refactoring of handles
[gitmo/Moose.git] / lib / Moose.pm
index 09a9603..ecc8801 100644 (file)
@@ -4,20 +4,18 @@ package Moose;
 use strict;
 use warnings;
 
-our $VERSION   = '0.40';
+our $VERSION   = '0.55';
 our $AUTHORITY = 'cpan:STEVAN';
 
-use Scalar::Util 'blessed', 'reftype';
-use Carp         'confess';
-use Sub::Name    'subname';
+use Scalar::Util 'blessed';
+use Carp         'confess', 'croak', 'cluck';
 
 use Sub::Exporter;
 
-use Class::MOP 0.51;
+use Class::MOP;
 
 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,102 +78,102 @@ 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) {
                     Class::MOP::load_class($super);
+                    croak "You cannot inherit from a Moose Role ($super)"
+                        if $super->can('meta')  && 
+                           blessed $super->meta &&
+                           $super->meta->isa('Moose::Meta::Role')
                 }
 
+
+
                 # this checks the metaclass to make sure
                 # it is correct, sometimes it can get out
                 # 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 );
-            };
-        },
-        metaclass => sub {
-            my $class = $CALLER;
-            return subname 'Moose::metaclass' => sub { 
-                $class->meta;
-            };
+            });
         },
         make_immutable => sub {
             my $class = $CALLER;
-            return subname 'Moose::make_immutable' => sub {
+            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;
@@ -196,11 +194,11 @@ use Moose::Util ();
     sub _get_caller{
         my $offset = 1;
         return
-            ref $_[1] && defined $_[1]->{into}
-            ? $_[1]->{into}
-            : ref $_[1] && defined $_[1]->{into_level}
-            ? caller($offset + $_[1]->{into_level})
-            : caller($offset);
+            (ref $_[1] && defined $_[1]->{into})
+                ? $_[1]->{into}
+                : (ref $_[1] && defined $_[1]->{into_level})
+                    ? caller($offset + $_[1]->{into_level})
+                    : caller($offset);
     }
 
     sub import {
@@ -221,6 +219,21 @@ use Moose::Util ();
 
         goto $exporter;
     }
+    
+    # NOTE:
+    # This is for special use by 
+    # some modules and stuff, I 
+    # dont know if it is sane enough
+    # to document actually.
+    # - SL
+    sub __CURRY_EXPORTS_FOR_CLASS__ {
+        $CALLER = shift;
+        ($CALLER ne 'Moose')
+            || croak "_import_into must be called a function, not a method";
+        ($CALLER->can('meta') && $CALLER->meta->isa('Class::MOP::Class'))
+            || croak "Cannot call _import_into on a package ($CALLER) without a metaclass";        
+        return map { $_ => $exports{$_}->() } (@_ ? @_ : keys %exports);
+    }
 
     sub unimport {
         no strict 'refs';
@@ -235,7 +248,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
@@ -313,62 +325,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<Class::MOP>, 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<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>.
-
-=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<post> modern, I thought it was just I<modern>?
-
-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<postmodern> 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<Class::MOP>, 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<MooseX::> 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<Task::Moose> which aims to keep an up to date, easily 
+installable list of these extensions. 
 
 =head1 BUILDING CLASSES WITH MOOSE
 
@@ -385,11 +357,10 @@ L<Moose::Object>) 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<Moose::Object>. There is however, one exception.
 
 =over 4
 
@@ -397,6 +368,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<extends (@superclasses)>
 
 This function will set the superclass(es) for the current class.
@@ -408,8 +389,7 @@ superclasses still properly inherit from L<Moose::Object>.
 
 =item B<with (@roles)>
 
-This will apply a given set of C<@roles> to the local class. Role support
-is currently under heavy development; see L<Moose::Role> for more details.
+This will apply a given set of C<@roles> to the local class. 
 
 =item B<has $name =E<gt> %options>
 
@@ -428,7 +408,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<reader>, I<writer> and I<accessor> options inherited from
-L<Class::MOP::Attribute>.
+L<Class::MOP::Attribute>, however if you use those, you won't need the I<is> 
+option.
 
 =item I<isa =E<gt> $type_name>
 
@@ -473,22 +454,6 @@ If an attribute is marked as lazy it B<must> have a default supplied.
 This tells the accessor whether to automatically dereference the value returned.
 This is only legal if your C<isa> option is either C<ArrayRef> or C<HashRef>.
 
-=item I<metaclass =E<gt> $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<has> 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<Moose::Meta::Attribute::Custom::$metaclass_name> exists. If it does, Moose
-will then check to see if that has the method C<register_implementation>, which
-should return the actual name of the custom attribute metaclass. If there is no
-C<register_implementation> method, it will fall back to using
-B<Moose::Meta::Attribute::Custom::$metaclass_name> as the metaclass name.
-
 =item I<trigger =E<gt> $code>
 
 The I<trigger> option is a CODE reference which will be called after the value of
@@ -503,10 +468,6 @@ The I<handles> 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<NOTE:> 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<NOTE:> 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.
 
@@ -606,6 +567,37 @@ a HASH ref) of the methods you want mapped.
 
 =back
 
+=item I<metaclass =E<gt> $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<has> 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<Moose::Cookbook::Recipe11> 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<Moose::Meta::Attribute::Custom::$metaclass_name> exists. If it does, Moose
+will then check to see if that has the method C<register_implementation>, which
+should return the actual name of the custom attribute metaclass. If there is no
+C<register_implementation> method, it will fall back to using
+B<Moose::Meta::Attribute::Custom::$metaclass_name> as the metaclass name.
+
+=item I<traits =E<gt> [ @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<metaclass> 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<metaclass>, 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<Moose::Meta::Attribute::Custom::Trait::$role_name> exists. If it does, Moose
+will then check to see if that has the method C<register_implementation>, which
+should return the actual name of the custom attribute trait. If there is no
+C<register_implementation> method, it will fall back to using
+B<Moose::Meta::Attribute::Custom::Trait::$metaclass_name> as the trait name.
+
 =back
 
 =item B<has +$name =E<gt> %options>
@@ -684,8 +676,12 @@ Change if the attribute lazily initializes the slot.
 
 =item I<isa>
 
-You I<are> allowed to change the type, B<if and only if> the new type is a
-subtype of the old type.
+You I<are> 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<handles>
 
@@ -697,6 +693,17 @@ allowed to I<change> one.
 You are allowed to B<add> a new C<builder> definition, but you are B<not>
 allowed to I<change> one.
 
+=item I<metaclass>
+
+You are allowed to B<add> a new C<metaclass> definition, but you are
+B<not> allowed to I<change> one.
+
+=item I<traits>
+
+You are allowed to B<add> additional traits to the C<traits> definition.
+These traits will be composed into the attribute, but pre-existing traits
+B<are not> overridden, or removed.
+
 =back
 
 =item B<before $name|@names =E<gt> sub { ... }>
@@ -728,18 +735,18 @@ method call and the C<SUPER::> pseudo-package; it is really your choice.
 The keyword C<inner>, much like C<super>, is a no-op outside of the context of
 an C<augment> method. You can think of C<inner> as being the inverse of
 C<super>; the details of how C<inner> and C<augment> work is best described in
-the L<Moose::Cookbook>.
+the L<Moose::Cookbook::Recipe6>.
 
 =item B<augment ($name, &sub)>
 
 An C<augment> method, is a way of explicitly saying "I am augmenting this
 method from my superclass". Once again, the details of how C<inner> and
-C<augment> work is best described in the L<Moose::Cookbook>.
+C<augment> work is best described in the L<Moose::Cookbook::Recipe6>.
 
 =item B<confess>
 
 This is the C<Carp::confess> 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<blessed>
 
@@ -829,6 +836,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<EXTENDING AND EMBEDDING MOOSE> 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<Class::MOP>, 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<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>.
+
+=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<post> modern, I thought it was just I<modern>?
+
+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<postmodern> object system.
+
+Nuff Said.
+
 =back
 
 =head1 ACKNOWLEDGEMENTS
@@ -845,7 +921,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.
@@ -868,12 +944,23 @@ technologies.
 
 =item The Moose mailing list - moose@perl.org
 
-=item Moose stats on ohloh.net - L<http://www.ohloh.net/projects/5788>
+=item Moose stats on ohloh.net - L<http://www.ohloh.net/projects/moose>
 
 =item Several Moose extension modules in the L<MooseX::> namespace.
 
 =back
 
+=head2 Books
+
+=over 4
+
+=item The Art of the MetaObject Protocol
+
+I mention this in the L<Class::MOP> docs too, this book was critical in 
+the development of both modules and is highly recommended.
+
+=back
+
 =head2 Papers
 
 =over 4
@@ -892,6 +979,15 @@ All complex software has bugs lurking in it, and this module is no
 exception. If you find a bug please either email me, or add the bug
 to cpan-RT.
 
+=head1 FEATURE REQUESTS
+
+We are very strict about what features we add to the Moose core, especially 
+the user-visible features. Instead we have made sure that the underlying 
+meta-system of Moose is as extensible as possible so that you can add your 
+own features easily. That said, occasionally there is a feature needed in the 
+meta-system to support your planned extension, in which case you should 
+either email the mailing list or join us on irc at #moose to discuss.
+
 =head1 AUTHOR
 
 Stevan Little E<lt>stevan@iinteractive.comE<gt>
@@ -930,6 +1026,8 @@ Yuval (nothingmuch) Kogman
 
 Chris (perigrin) Prather
 
+Wallace (wreis) Reis
+
 Jonathan (jrockway) Rockway
 
 Piotr (dexter) Roszatycki