X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoo.pm;h=6bf3fc007ea14c150d47e872f53bc46a1b38c506;hb=349ea75bb916f05ad325841b500e1fd0a9d5f2e4;hp=a5f869cc3d5476d0a2b42f9f71c6b9c76b21f326;hpb=59b8836108f8ace2becbf0cebd138705d6624bf0;p=gitmo%2FMoo.git diff --git a/lib/Moo.pm b/lib/Moo.pm index a5f869c..6bf3fc0 100644 --- a/lib/Moo.pm +++ b/lib/Moo.pm @@ -5,7 +5,7 @@ use Moo::_Utils; use B 'perlstring'; use Sub::Defer (); -our $VERSION = '1.000007'; # 1.0.7 +our $VERSION = '1.003000'; $VERSION = eval $VERSION; require Moo::sification; @@ -22,11 +22,10 @@ sub import { my $target = caller; my $class = shift; strictures->import; - if ($Moo::Role::INFO{$target} and $Moo::Role::INFO{$target}{is_role}) { + if ($Role::Tiny::INFO{$target} and $Role::Tiny::INFO{$target}{is_role}) { die "Cannot import Moo into a role"; } - return if $MAKERS{$target}; # already exported into this package - $MAKERS{$target} = { is_class => 1 }; + $MAKERS{$target} ||= {}; _install_tracked $target => extends => sub { $class->_set_superclasses($target, @_); $class->_maybe_reset_handlemoose($target); @@ -38,12 +37,18 @@ sub import { $class->_maybe_reset_handlemoose($target); }; _install_tracked $target => has => sub { - my ($name_proto, %spec) = @_; - my $name_isref = ref $name_proto eq 'ARRAY'; - foreach my $name ($name_isref ? @$name_proto : $name_proto) { - # Note that when $name_proto is an arrayref, each attribute + my $name_proto = shift; + my @name_proto = ref $name_proto eq 'ARRAY' ? @$name_proto : $name_proto; + if (@_ % 2 != 0) { + require Carp; + Carp::croak("Invalid options for " . join(', ', map "'$_'", @name_proto) + . " attribute(s): even number of arguments expected, got " . scalar @_) + } + my %spec = @_; + foreach my $name (@name_proto) { + # Note that when multiple attributes specified, each attribute # needs a separate \%specs hashref - my $spec_ref = $name_isref ? +{%spec} : \%spec; + my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec; $class->_constructor_maker_for($target) ->register_attribute_specs($name, $spec_ref); $class->_accessor_maker_for($target) @@ -59,6 +64,8 @@ sub import { return; }; } + return if $MAKERS{$target}{is_class}; # already exported into this package + $MAKERS{$target}{is_class} = 1; { no strict 'refs'; @{"${target}::ISA"} = do { @@ -92,10 +99,13 @@ sub _set_superclasses { Moo->_constructor_maker_for($target) ->register_attribute_specs(%{$old->all_attribute_specs}); } + elsif (!$target->isa('Moo::Object')) { + Moo->_constructor_maker_for($target); + } no warnings 'once'; # piss off. -- mst $Moo::HandleMoose::MOUSE{$target} = [ grep defined, map Mouse::Util::find_meta($_), @_ - ] if $INC{"Mouse.pm"}; + ] if Mouse::Util->can('find_meta'); } sub _maybe_reset_handlemoose { @@ -164,7 +174,7 @@ sub _constructor_maker_for { construction_string => ( $moo_constructor ? ($con ? $con->construction_string : undef) - : ('$class->'.$target.'::SUPER::new(@_)') + : ('$class->'.$target.'::SUPER::new($class->can(q[FOREIGNBUILDARGS]) ? $class->FOREIGNBUILDARGS(@_) : @_)') ), subconstructor_handler => ( ' if ($Moo::MAKERS{$class}) {'."\n" @@ -187,7 +197,7 @@ sub _constructor_maker_for { =head1 NAME -Moo - Minimalist Object Orientation (with Moose compatiblity) +Moo - Minimalist Object Orientation (with Moose compatibility) =head1 SYNOPSIS @@ -211,7 +221,7 @@ Moo - Minimalist Object Orientation (with Moose compatiblity) isa => sub { die "Only SWEET-TREATZ supported!" unless $_[0] eq 'SWEET-TREATZ' }, -); + ); has pounds => ( is => 'rw', @@ -280,6 +290,10 @@ metaclasses for your L and L packages, so you should be able to use them in L code without anybody ever noticing you aren't using L everywhere. +L will also create L for +classes and roles, so that C<< isa => 'MyClass' >> and C<< isa => 'MyRole' >> +work the same as for L classes and roles. + Extending a L class or consuming a L will also work. So will extending a L class or consuming a L - but note @@ -307,6 +321,15 @@ to your code before Moose is loaded, but bear in mind that this switch is currently global and turns the mechanism off entirely so don't put this in library code. +=head1 MOO AND CLASS::XSACCESSOR + +If a new enough version of L is available, it +will be used to generate simple accessors, readers, and writers for +a speed boost. Simple accessors are those without lazy defaults, +type checks/coercions, or triggers. Readers and writers generated +by L will behave slightly differently: they will +reject attempts to call them with the incorrect number of parameters. + =head1 MOO VERSUS ANY::MOOSE L will load L normally, and L in a program using @@ -357,6 +380,13 @@ passed to the constructor. This method should always return a hash reference of named options. +=head2 FOREIGNBUILDARGS + +If you are inheriting from a non-Moo class, the arguments passed to the parent +class constructor can be manipulated by defining a C method. +It will receive the same arguments as C, and should return a list +of arguments to pass to the parent class constructor. + =head2 BUILD Define a C method on your class and the constructor will automatically @@ -414,6 +444,21 @@ class. An error will be raised if these roles have conflicting methods. Declares an attribute for the class. + package Foo; + use Moo; + has 'attr' => ( + is => 'ro' + ); + + package Bar; + use Moo; + extends 'Foo'; + has '+attr' => ( + default => sub { "blah" }, + ); + +Using the C<+> notation, it's possible to override an attribute. + The options for C are as follows: =over 2 @@ -429,7 +474,9 @@ C generates a reader like C, but also sets C to 1 and C to C<_build_${attribute_name}> to allow on-demand generated attributes. This feature was my attempt to fix my incompetence when originally designing C, and is also implemented by -L. +L. There is, however, nothing to stop you +using C and C yourself with C or C - it's just that +this isn't generally a good idea so we don't provide a shortcut for it. C generates a reader like C, but also sets C to C<_set_${attribute_name}> for attributes that are designed to be written @@ -449,6 +496,9 @@ one should do die "$_[0] is not a number!" unless looks_like_number $_[0] }, +Note that the return value is ignored, only whether the sub lives or +dies matters. + L Since L does B run the C check before C if a coercion @@ -479,7 +529,7 @@ Takes a coderef which is meant to coerce the attribute. The basic idea is to do something like the following: coerce => sub { - $_[0] + 1 unless $_[0] % 2 + $_[0] % 2 ? $_[0] : $_[0] + 1 }, Note that L will always fire your coercion: this is to permit @@ -508,11 +558,11 @@ Takes a hashref un => 'one', } -=item * trigger +=item * C Takes a coderef which will get called any time the attribute is set. This -includes the constructor. Coderef will be invoked against the object with the -new value as an argument. +includes the constructor, but not default or built values. Coderef will be +invoked against the object with the new value as an argument. If you set this to just C<1>, it generates a trigger which calls the C<_trigger_${attr_name}> method on C<$self>. This feature comes from @@ -530,6 +580,10 @@ to populate an attribute if no value is supplied to the constructor - or if the attribute is lazy, when the attribute is first retrieved if no value has yet been provided. +If a simple scalar is provided, it will be inlined as a string. Any non-code +reference (hash, array) will result in an error - for that case instead use +a code reference that returns the desired value. + Note that if your default is fired during new() there is no guarantee that other attributes have been populated yet so you should not rely on their existence. @@ -542,7 +596,7 @@ Takes a method name which will return true if an attribute has a value. If you set this to just C<1>, the predicate is automatically named C if your attribute's name does not start with an -underscore, or <_has_${attr_name_without_the_underscore}> if it does. +underscore, or C<_has_${attr_name_without_the_underscore}> if it does. This feature comes from L. =item * C @@ -556,8 +610,14 @@ Moo will call $self->$builder; -If you set this to just C<1>, the predicate is automatically named -C<_build_${attr_name}>. This feature comes from L. +The following features come from L: + +If you set this to just C<1>, the builder is automatically named +C<_build_${attr_name}>. + +If you set this to a coderef or code-convertible object, that variable will be +installed under C<$class::_build_${attr_name}> and the builder set to the same +name. =item * C @@ -603,6 +663,13 @@ common use of this is to make an underscored attribute have a non-underscored initialization name. C means that passing the value in on instantiation is ignored. +=item * C + +Takes either a coderef or array of coderefs which is meant to transform the +given attributes specifications if necessary when upgrading to a Moose role or +class. You shouldn't need this by default, but is provided as a means of +possible extensibility. + =back =head2 before @@ -680,7 +747,7 @@ API will encourage the use of other type systems as well, since it's probably the weakest part of Moose design-wise. C is not supported in core since the author considers it to be a -bad idea but may be supported by an extension in future. Meanwhile C or +bad idea and Moose best practices recommend avoiding it. Meanwhile C or C are more likely to be able to fulfill your needs. There is no meta object. If you need this level of complexity you wanted @@ -711,13 +778,15 @@ The C method is not provided by default. The author suggests loading L into C (via C for example) and using C<$obj-E$::Dwarn()> instead. -L only supports coderefs, because doing otherwise is usually a -mistake anyway. +L only supports coderefs and plain scalars, because passing a hash +or array reference as a default is almost always incorrect since the value is +then shared between all objects using that default. C is not supported; you are instead encouraged to use the C<< is => 'lazy' >> option supported by L and L. -C is not supported since the author considers it a bad idea. +C is not supported since the author considers it a bad idea and +it has been considered best practice to avoid it for some time. C will show up in a L metaclass created from your class but is otherwise ignored. Then again, L ignores it as well, so this @@ -763,14 +832,27 @@ Finally, Moose requires you to call at the end of your class to get an inlined (i.e. not horribly slow) constructor. Moo does it automatically the first time ->new is called -on your class. +on your class. (C is a no-op in Moo to ease migration.) + +An extension L exists to ease translating Moose packages +to Moo by providing a more Moose-like interface. =head1 SUPPORT Users' IRC: #moose on irc.perl.org +=for html (click for instant chatroom login) + Development and contribution IRC: #web-simple on irc.perl.org +=for html (click for instant chatroom login) + +Bugtracker: L + +Git repository: L + +Git web access: L + =head1 AUTHOR mst - Matt S. Trout (cpan:MSTROUT) @@ -801,6 +883,10 @@ ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) tobyink - Toby Inkster (cpan:TOBYINK) +haarg - Graham Knop (cpan:HAARG) + +mattp - Matt Phillips (cpan:MATTP) + =head1 COPYRIGHT Copyright (c) 2010-2011 the Moo L and L @@ -809,6 +895,6 @@ as listed above. =head1 LICENSE This library is free software and may be distributed under the same terms -as perl itself. +as perl itself. See L. =cut