Filename | /opt/perl-5.18.1/lib/site_perl/5.18.1/Moo.pm |
Statements | Executed 220 statements in 3.28ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
5 | 2 | 1 | 5.14ms | 5.67ms | _accessor_maker_for | Moo::
3 | 2 | 2 | 1.82ms | 10.4ms | _constructor_maker_for (recurses: max depth 1, inclusive time 5.76ms) | Moo::
1 | 1 | 1 | 1.34ms | 1.91ms | BEGIN@4 | Moo::
3 | 3 | 2 | 917µs | 4.37ms | import | Moo::
1 | 1 | 1 | 739µs | 974µs | BEGIN@3 | Moo::
1 | 1 | 1 | 736µs | 1.04ms | BEGIN@6 | Moo::
18 | 4 | 1 | 89µs | 333µs | _install_tracked | Moo::
2 | 1 | 1 | 12µs | 17µs | _maybe_reset_handlemoose | Moo::
1 | 1 | 1 | 11µs | 23µs | BEGIN@105 | Moo::
1 | 1 | 1 | 10µs | 752µs | BEGIN@5 | Moo::
1 | 1 | 1 | 9µs | 24µs | BEGIN@70 | Moo::
0 | 0 | 0 | 0s | 0s | __ANON__[:33] | Moo::
0 | 0 | 0 | 0s | 0s | __ANON__[:38] | Moo::
0 | 0 | 0 | 0s | 0s | __ANON__[:59] | Moo::
0 | 0 | 0 | 0s | 0s | __ANON__[:65] | Moo::
0 | 0 | 0 | 0s | 0s | _set_superclasses | Moo::
0 | 0 | 0 | 0s | 0s | unimport | Moo::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Moo; | ||||
2 | |||||
3 | 3 | 132µs | 3 | 1.04ms | # spent 974µs (739+235) within Moo::BEGIN@3 which was called:
# once (739µs+235µs) by Foo::Moo::BEGIN@116 at line 3 # spent 974µs making 1 call to Moo::BEGIN@3
# spent 47µs making 1 call to strictures::import
# spent 22µs making 1 call to strictures::VERSION |
4 | 2 | 139µs | 2 | 1.98ms | # spent 1.91ms (1.34+572µs) within Moo::BEGIN@4 which was called:
# once (1.34ms+572µs) by Foo::Moo::BEGIN@116 at line 4 # spent 1.91ms making 1 call to Moo::BEGIN@4
# spent 69µs making 1 call to Exporter::import |
5 | 2 | 43µs | 2 | 1.49ms | # spent 752µs (10+742) within Moo::BEGIN@5 which was called:
# once (10µs+742µs) by Foo::Moo::BEGIN@116 at line 5 # spent 752µs making 1 call to Moo::BEGIN@5
# spent 742µs making 1 call to Exporter::import |
6 | 2 | 655µs | 1 | 1.04ms | # spent 1.04ms (736µs+306µs) within Moo::BEGIN@6 which was called:
# once (736µs+306µs) by Foo::Moo::BEGIN@116 at line 6 # spent 1.04ms making 1 call to Moo::BEGIN@6 |
7 | |||||
8 | 1 | 900ns | our $VERSION = '1.003001'; | ||
9 | 1 | 20µs | $VERSION = eval $VERSION; # spent 3µs executing statements in string eval | ||
10 | |||||
11 | 1 | 84µs | require Moo::sification; | ||
12 | |||||
13 | 1 | 200ns | our %MAKERS; | ||
14 | |||||
15 | # spent 333µs (89+244) within Moo::_install_tracked which was called 18 times, avg 18µs/call:
# 9 times (39µs+120µs) by Moo::import at line 65, avg 18µs/call
# 3 times (23µs+54µs) by Moo::import at line 33, avg 26µs/call
# 3 times (14µs+35µs) by Moo::import at line 38, avg 16µs/call
# 3 times (12µs+35µs) by Moo::import at line 59, avg 16µs/call | ||||
16 | 18 | 8µs | my ($target, $name, $code) = @_; | ||
17 | 18 | 15µs | $MAKERS{$target}{exports}{$name} = $code; | ||
18 | 18 | 60µs | 18 | 244µs | _install_coderef "${target}::${name}" => "Moo::${name}" => $code; # spent 244µs making 18 calls to Moo::_Utils::_install_coderef, avg 14µs/call |
19 | } | ||||
20 | |||||
21 | # spent 4.37ms (917µs+3.46) within Moo::import which was called 3 times, avg 1.46ms/call:
# once (812µs+1.57ms) by Foo::Moo::BEGIN@116 at line 116 of fastest.pl
# once (52µs+1.01ms) by Method::Generate::Constructor::BEGIN@186 at line 186 of Method/Generate/Constructor.pm
# once (53µs+875µs) by Foo::Moo::QS::BEGIN@129 at line 129 of fastest.pl | ||||
22 | 3 | 3µs | my $target = caller; | ||
23 | 3 | 2µs | my $class = shift; | ||
24 | 3 | 4µs | 3 | 133µs | strictures->import; # spent 133µs making 3 calls to strictures::import, avg 44µs/call |
25 | 3 | 1µs | if ($Role::Tiny::INFO{$target} and $Role::Tiny::INFO{$target}{is_role}) { | ||
26 | die "Cannot import Moo into a role"; | ||||
27 | } | ||||
28 | 3 | 3µs | $MAKERS{$target} ||= {}; | ||
29 | _install_tracked $target => extends => sub { | ||||
30 | $class->_set_superclasses($target, @_); | ||||
31 | $class->_maybe_reset_handlemoose($target); | ||||
32 | return; | ||||
33 | 3 | 15µs | 3 | 78µs | }; # spent 78µs making 3 calls to Moo::_install_tracked, avg 26µs/call |
34 | _install_tracked $target => with => sub { | ||||
35 | require Moo::Role; | ||||
36 | Moo::Role->apply_roles_to_package($target, @_); | ||||
37 | $class->_maybe_reset_handlemoose($target); | ||||
38 | 3 | 11µs | 3 | 48µs | }; # spent 48µs making 3 calls to Moo::_install_tracked, avg 16µs/call |
39 | _install_tracked $target => has => sub { | ||||
40 | 2 | 900ns | my $name_proto = shift; | ||
41 | 2 | 3µs | my @name_proto = ref $name_proto eq 'ARRAY' ? @$name_proto : $name_proto; | ||
42 | 2 | 1µs | if (@_ % 2 != 0) { | ||
43 | require Carp; | ||||
44 | Carp::croak("Invalid options for " . join(', ', map "'$_'", @name_proto) | ||||
45 | . " attribute(s): even number of arguments expected, got " . scalar @_) | ||||
46 | } | ||||
47 | 2 | 3µs | my %spec = @_; | ||
48 | 2 | 2µs | foreach my $name (@name_proto) { | ||
49 | # Note that when multiple attributes specified, each attribute | ||||
50 | # needs a separate \%specs hashref | ||||
51 | 2 | 2µs | my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec; | ||
52 | 2 | 9µs | 4 | 10.4ms | $class->_constructor_maker_for($target) # spent 10.4ms making 2 calls to Moo::_constructor_maker_for, avg 5.19ms/call
# spent 19µs making 2 calls to Method::Generate::Constructor::register_attribute_specs, avg 10µs/call |
53 | ->register_attribute_specs($name, $spec_ref); | ||||
54 | 2 | 7µs | 4 | 437µs | $class->_accessor_maker_for($target) # spent 428µs making 2 calls to Method::Generate::Accessor::generate_method, avg 214µs/call
# spent 8µs making 2 calls to Moo::_accessor_maker_for, avg 4µs/call |
55 | ->generate_method($target, $name, $spec_ref); | ||||
56 | 2 | 6µs | 2 | 17µs | $class->_maybe_reset_handlemoose($target); # spent 17µs making 2 calls to Moo::_maybe_reset_handlemoose, avg 8µs/call |
57 | } | ||||
58 | 2 | 8µs | return; | ||
59 | 3 | 12µs | 3 | 48µs | }; # spent 48µs making 3 calls to Moo::_install_tracked, avg 16µs/call |
60 | 3 | 2µs | foreach my $type (qw(before after around)) { | ||
61 | _install_tracked $target => $type => sub { | ||||
62 | require Class::Method::Modifiers; | ||||
63 | _install_modifier($target, $type, @_); | ||||
64 | return; | ||||
65 | 9 | 36µs | 9 | 159µs | }; # spent 159µs making 9 calls to Moo::_install_tracked, avg 18µs/call |
66 | } | ||||
67 | 3 | 2µs | return if $MAKERS{$target}{is_class}; # already exported into this package | ||
68 | 3 | 2µs | $MAKERS{$target}{is_class} = 1; | ||
69 | { | ||||
70 | 5 | 334µs | 2 | 38µs | # spent 24µs (9+14) within Moo::BEGIN@70 which was called:
# once (9µs+14µs) by Foo::Moo::BEGIN@116 at line 70 # spent 24µs making 1 call to Moo::BEGIN@70
# spent 14µs making 1 call to strict::unimport |
71 | @{"${target}::ISA"} = do { | ||||
72 | 4 | 92µs | require Moo::Object; ('Moo::Object'); | ||
73 | 3 | 26µs | } unless @{"${target}::ISA"}; | ||
74 | } | ||||
75 | 3 | 18µs | 3 | 2.89ms | if ($INC{'Moo/HandleMoose.pm'}) { # spent 2.89ms making 3 calls to Moo::HandleMoose::inject_fake_metaclass_for, avg 964µs/call |
76 | Moo::HandleMoose::inject_fake_metaclass_for($target); | ||||
77 | } | ||||
78 | } | ||||
79 | |||||
80 | sub unimport { | ||||
81 | my $target = caller; | ||||
82 | _unimport_coderefs($target, $MAKERS{$target}); | ||||
83 | } | ||||
84 | |||||
85 | sub _set_superclasses { | ||||
86 | my $class = shift; | ||||
87 | my $target = shift; | ||||
88 | foreach my $superclass (@_) { | ||||
89 | _load_module($superclass); | ||||
90 | if ($INC{"Role/Tiny.pm"} && $Role::Tiny::INFO{$superclass}) { | ||||
91 | require Carp; | ||||
92 | Carp::croak("Can't extend role '$superclass'"); | ||||
93 | } | ||||
94 | } | ||||
95 | # Can't do *{...} = \@_ or 5.10.0's mro.pm stops seeing @ISA | ||||
96 | @{*{_getglob("${target}::ISA")}{ARRAY}} = @_; | ||||
97 | if (my $old = delete $Moo::MAKERS{$target}{constructor}) { | ||||
98 | delete _getstash($target)->{new}; | ||||
99 | Moo->_constructor_maker_for($target) | ||||
100 | ->register_attribute_specs(%{$old->all_attribute_specs}); | ||||
101 | } | ||||
102 | elsif (!$target->isa('Moo::Object')) { | ||||
103 | Moo->_constructor_maker_for($target); | ||||
104 | } | ||||
105 | 2 | 1.10ms | 2 | 34µs | # spent 23µs (11+11) within Moo::BEGIN@105 which was called:
# once (11µs+11µs) by Foo::Moo::BEGIN@116 at line 105 # spent 23µs making 1 call to Moo::BEGIN@105
# spent 11µs making 1 call to warnings::unimport |
106 | $Moo::HandleMoose::MOUSE{$target} = [ | ||||
107 | grep defined, map Mouse::Util::find_meta($_), @_ | ||||
108 | ] if Mouse::Util->can('find_meta'); | ||||
109 | } | ||||
110 | |||||
111 | # spent 17µs (12+5) within Moo::_maybe_reset_handlemoose which was called 2 times, avg 8µs/call:
# 2 times (12µs+5µs) by Moo::has at line 56, avg 8µs/call | ||||
112 | 2 | 1µs | my ($class, $target) = @_; | ||
113 | 2 | 9µs | 2 | 5µs | if ($INC{"Moo/HandleMoose.pm"}) { # spent 5µs making 2 calls to Moo::HandleMoose::maybe_reinject_fake_metaclass_for, avg 2µs/call |
114 | Moo::HandleMoose::maybe_reinject_fake_metaclass_for($target); | ||||
115 | } | ||||
116 | } | ||||
117 | |||||
118 | sub _accessor_maker_for { | ||||
119 | 5 | 2µs | my ($class, $target) = @_; | ||
120 | 5 | 5µs | return unless $MAKERS{$target}; | ||
121 | 5 | 17µs | $MAKERS{$target}{accessor} ||= do { | ||
122 | 3 | 2µs | my $maker_class = do { | ||
123 | 3 | 1µs | if (my $m = do { | ||
124 | 3 | 17µs | 6 | 12µs | if (my $defer_target = # spent 8µs making 3 calls to Sub::Defer::defer_info, avg 3µs/call
# spent 3µs making 3 calls to UNIVERSAL::can, avg 1µs/call |
125 | (Sub::Defer::defer_info($target->can('new'))||[])->[0] | ||||
126 | ) { | ||||
127 | my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/); | ||||
128 | $MAKERS{$pkg} && $MAKERS{$pkg}{accessor}; | ||||
129 | } else { | ||||
130 | 3 | 700ns | undef; | ||
131 | } | ||||
132 | }) { | ||||
133 | ref($m); | ||||
134 | } else { | ||||
135 | 3 | 98µs | require Method::Generate::Accessor; | ||
136 | 3 | 400ns | 'Method::Generate::Accessor' | ||
137 | } | ||||
138 | }; | ||||
139 | 3 | 9µs | 3 | 43µs | $maker_class->new; # spent 43µs making 3 calls to Moo::Object::new, avg 14µs/call |
140 | } | ||||
141 | } | ||||
142 | |||||
143 | # spent 10.4ms (1.82+8.57) within Moo::_constructor_maker_for which was called 3 times, avg 3.46ms/call:
# 2 times (1.76ms+8.62ms) by Moo::has at line 52, avg 5.19ms/call
# once (56µs+-56µs) by Moo::_constructor_maker_for at line 187 of Method/Generate/Constructor.pm | ||||
144 | 3 | 2µs | my ($class, $target, $select_super) = @_; | ||
145 | 3 | 2µs | return unless $MAKERS{$target}; | ||
146 | 3 | 17µs | $MAKERS{$target}{constructor} ||= do { | ||
147 | 3 | 135µs | require Method::Generate::Constructor; | ||
148 | 3 | 800ns | require Sub::Defer; | ||
149 | 3 | 300ns | my ($moo_constructor, $con); | ||
150 | |||||
151 | 3 | 1µs | if ($select_super && $MAKERS{$select_super}) { | ||
152 | $moo_constructor = 1; | ||||
153 | $con = $MAKERS{$select_super}{constructor}; | ||||
154 | } else { | ||||
155 | 3 | 33µs | 3 | 9µs | my $t_new = $target->can('new'); # spent 9µs making 3 calls to UNIVERSAL::can, avg 3µs/call |
156 | 3 | 2µs | if ($t_new) { | ||
157 | 3 | 15µs | 3 | 3µs | if ($t_new == Moo::Object->can('new')) { # spent 3µs making 3 calls to UNIVERSAL::can, avg 967ns/call |
158 | $moo_constructor = 1; | ||||
159 | } elsif (my $defer_target = (Sub::Defer::defer_info($t_new)||[])->[0]) { | ||||
160 | my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/); | ||||
161 | if ($MAKERS{$pkg}) { | ||||
162 | $moo_constructor = 1; | ||||
163 | $con = $MAKERS{$pkg}{constructor}; | ||||
164 | } | ||||
165 | } | ||||
166 | } else { | ||||
167 | $moo_constructor = 1; # no other constructor, make a Moo one | ||||
168 | } | ||||
169 | }; | ||||
170 | ($con ? ref($con) : 'Method::Generate::Constructor') | ||||
171 | ->new( | ||||
172 | package => $target, | ||||
173 | accessor_generator => $class->_accessor_maker_for($target), | ||||
174 | construction_string => ( | ||||
175 | $moo_constructor | ||||
176 | ? ($con ? $con->construction_string : undef) | ||||
177 | : ('$class->'.$target.'::SUPER::new($class->can(q[FOREIGNBUILDARGS]) ? $class->FOREIGNBUILDARGS(@_) : @_)') | ||||
178 | ), | ||||
179 | subconstructor_handler => ( | ||||
180 | ' if ($Moo::MAKERS{$class}) {'."\n" | ||||
181 | .' '.$class.'->_constructor_maker_for($class,'.perlstring($target).');'."\n" | ||||
182 | .' return $class->new(@_)'.";\n" | ||||
183 | .' } elsif ($INC{"Moose.pm"} and my $meta = Class::MOP::get_metaclass_by_name($class)) {'."\n" | ||||
184 | .' return $meta->new_object($class->BUILDARGS(@_));'."\n" | ||||
185 | .' }'."\n" | ||||
186 | ), | ||||
187 | ) | ||||
188 | ->install_delayed | ||||
189 | 3 | 43µs | 15 | 7.01ms | ->register_attribute_specs(%{$con?$con->all_attribute_specs:{}}) # spent 5.67ms making 3 calls to Moo::_accessor_maker_for, avg 1.89ms/call
# spent 1.18ms making 2 calls to Method::Generate::Constructor::new, avg 592µs/call
# spent 120µs making 3 calls to Method::Generate::Constructor::install_delayed, avg 40µs/call
# spent 20µs making 3 calls to Method::Generate::Constructor::register_attribute_specs, avg 7µs/call
# spent 18µs making 1 call to Moo::Object::new
# spent 5µs making 3 calls to B::perlstring, avg 2µs/call |
190 | } | ||||
191 | } | ||||
192 | |||||
193 | 1 | 4µs | 1; | ||
194 | =pod | ||||
195 | |||||
196 | =encoding utf-8 | ||||
197 | |||||
198 | =head1 NAME | ||||
199 | |||||
200 | Moo - Minimalist Object Orientation (with Moose compatibility) | ||||
201 | |||||
202 | =head1 SYNOPSIS | ||||
203 | |||||
204 | package Cat::Food; | ||||
205 | |||||
206 | use Moo; | ||||
207 | |||||
208 | sub feed_lion { | ||||
209 | my $self = shift; | ||||
210 | my $amount = shift || 1; | ||||
211 | |||||
212 | $self->pounds( $self->pounds - $amount ); | ||||
213 | } | ||||
214 | |||||
215 | has taste => ( | ||||
216 | is => 'ro', | ||||
217 | ); | ||||
218 | |||||
219 | has brand => ( | ||||
220 | is => 'ro', | ||||
221 | isa => sub { | ||||
222 | die "Only SWEET-TREATZ supported!" unless $_[0] eq 'SWEET-TREATZ' | ||||
223 | }, | ||||
224 | ); | ||||
225 | |||||
226 | has pounds => ( | ||||
227 | is => 'rw', | ||||
228 | isa => sub { die "$_[0] is too much cat food!" unless $_[0] < 15 }, | ||||
229 | ); | ||||
230 | |||||
231 | 1; | ||||
232 | |||||
233 | And elsewhere: | ||||
234 | |||||
235 | my $full = Cat::Food->new( | ||||
236 | taste => 'DELICIOUS.', | ||||
237 | brand => 'SWEET-TREATZ', | ||||
238 | pounds => 10, | ||||
239 | ); | ||||
240 | |||||
241 | $full->feed_lion; | ||||
242 | |||||
243 | say $full->pounds; | ||||
244 | |||||
245 | =head1 DESCRIPTION | ||||
246 | |||||
247 | This module is an extremely light-weight subset of L<Moose> optimised for | ||||
248 | rapid startup and "pay only for what you use". | ||||
249 | |||||
250 | It also avoids depending on any XS modules to allow simple deployments. The | ||||
251 | name C<Moo> is based on the idea that it provides almost -- but not quite -- two | ||||
252 | thirds of L<Moose>. | ||||
253 | |||||
254 | Unlike L<Mouse> this module does not aim at full compatibility with | ||||
255 | L<Moose>'s surface syntax, preferring instead of provide full interoperability | ||||
256 | via the metaclass inflation capabilities described in L</MOO AND MOOSE>. | ||||
257 | |||||
258 | For a full list of the minor differences between L<Moose> and L<Moo>'s surface | ||||
259 | syntax, see L</INCOMPATIBILITIES WITH MOOSE>. | ||||
260 | |||||
261 | =head1 WHY MOO EXISTS | ||||
262 | |||||
263 | If you want a full object system with a rich Metaprotocol, L<Moose> is | ||||
264 | already wonderful. | ||||
265 | |||||
266 | However, sometimes you're writing a command line script or a CGI script | ||||
267 | where fast startup is essential, or code designed to be deployed as a single | ||||
268 | file via L<App::FatPacker>, or you're writing a CPAN module and you want it | ||||
269 | to be usable by people with those constraints. | ||||
270 | |||||
271 | I've tried several times to use L<Mouse> but it's 3x the size of Moo and | ||||
272 | takes longer to load than most of my Moo based CGI scripts take to run. | ||||
273 | |||||
274 | If you don't want L<Moose>, you don't want "less metaprotocol" like L<Mouse>, | ||||
275 | you want "as little as possible" -- which means "no metaprotocol", which is | ||||
276 | what Moo provides. | ||||
277 | |||||
278 | Better still, if you install and load L<Moose>, we set up metaclasses for your | ||||
279 | L<Moo> classes and L<Moo::Role> roles, so you can use them in L<Moose> code | ||||
280 | without ever noticing that some of your codebase is using L<Moo>. | ||||
281 | |||||
282 | Hence, Moo exists as its name -- Minimal Object Orientation -- with a pledge | ||||
283 | to make it smooth to upgrade to L<Moose> when you need more than minimal | ||||
284 | features. | ||||
285 | |||||
286 | =head1 MOO AND MOOSE | ||||
287 | |||||
288 | If L<Moo> detects L<Moose> being loaded, it will automatically register | ||||
289 | metaclasses for your L<Moo> and L<Moo::Role> packages, so you should be able | ||||
290 | to use them in L<Moose> code without anybody ever noticing you aren't using | ||||
291 | L<Moose> everywhere. | ||||
292 | |||||
293 | L<Moo> will also create L<Moose type constraints|Moose::Manual::Types> for | ||||
294 | classes and roles, so that C<< isa => 'MyClass' >> and C<< isa => 'MyRole' >> | ||||
295 | work the same as for L<Moose> classes and roles. | ||||
296 | |||||
297 | Extending a L<Moose> class or consuming a L<Moose::Role> will also work. | ||||
298 | |||||
299 | So will extending a L<Mouse> class or consuming a L<Mouse::Role> - but note | ||||
300 | that we don't provide L<Mouse> metaclasses or metaroles so the other way | ||||
301 | around doesn't work. This feature exists for L<Any::Moose> users porting to | ||||
302 | L<Moo>; enabling L<Mouse> users to use L<Moo> classes is not a priority for us. | ||||
303 | |||||
304 | This means that there is no need for anything like L<Any::Moose> for Moo | ||||
305 | code - Moo and Moose code should simply interoperate without problem. To | ||||
306 | handle L<Mouse> code, you'll likely need an empty Moo role or class consuming | ||||
307 | or extending the L<Mouse> stuff since it doesn't register true L<Moose> | ||||
308 | metaclasses like L<Moo> does. | ||||
309 | |||||
310 | If you want types to be upgraded to the L<Moose> types, use | ||||
311 | L<MooX::Types::MooseLike> and install the L<MooseX::Types> library to | ||||
312 | match the L<MooX::Types::MooseLike> library you're using - L<Moo> will | ||||
313 | load the L<MooseX::Types> library and use that type for the newly created | ||||
314 | metaclass. | ||||
315 | |||||
316 | If you need to disable the metaclass creation, add: | ||||
317 | |||||
318 | no Moo::sification; | ||||
319 | |||||
320 | to your code before Moose is loaded, but bear in mind that this switch is | ||||
321 | currently global and turns the mechanism off entirely so don't put this | ||||
322 | in library code. | ||||
323 | |||||
324 | =head1 MOO AND CLASS::XSACCESSOR | ||||
325 | |||||
326 | If a new enough version of L<Class::XSAccessor> is available, it | ||||
327 | will be used to generate simple accessors, readers, and writers for | ||||
328 | a speed boost. Simple accessors are those without lazy defaults, | ||||
329 | type checks/coercions, or triggers. Readers and writers generated | ||||
330 | by L<Class::XSAccessor> will behave slightly differently: they will | ||||
331 | reject attempts to call them with the incorrect number of parameters. | ||||
332 | |||||
333 | =head1 MOO VERSUS ANY::MOOSE | ||||
334 | |||||
335 | L<Any::Moose> will load L<Mouse> normally, and L<Moose> in a program using | ||||
336 | L<Moose> - which theoretically allows you to get the startup time of L<Mouse> | ||||
337 | without disadvantaging L<Moose> users. | ||||
338 | |||||
339 | Sadly, this doesn't entirely work, since the selection is load order dependent | ||||
340 | - L<Moo>'s metaclass inflation system explained above in L</MOO AND MOOSE> is | ||||
341 | significantly more reliable. | ||||
342 | |||||
343 | So if you want to write a CPAN module that loads fast or has only pure perl | ||||
344 | dependencies but is also fully usable by L<Moose> users, you should be using | ||||
345 | L<Moo>. | ||||
346 | |||||
347 | For a full explanation, see the article | ||||
348 | L<http://shadow.cat/blog/matt-s-trout/moo-versus-any-moose> which explains | ||||
349 | the differing strategies in more detail and provides a direct example of | ||||
350 | where L<Moo> succeeds and L<Any::Moose> fails. | ||||
351 | |||||
352 | =head1 IMPORTED METHODS | ||||
353 | |||||
354 | =head2 new | ||||
355 | |||||
356 | Foo::Bar->new( attr1 => 3 ); | ||||
357 | |||||
358 | or | ||||
359 | |||||
360 | Foo::Bar->new({ attr1 => 3 }); | ||||
361 | |||||
362 | =head2 BUILDARGS | ||||
363 | |||||
364 | sub BUILDARGS { | ||||
365 | my ( $class, @args ) = @_; | ||||
366 | |||||
367 | unshift @args, "attr1" if @args % 2 == 1; | ||||
368 | |||||
369 | return { @args }; | ||||
370 | }; | ||||
371 | |||||
372 | Foo::Bar->new( 3 ); | ||||
373 | |||||
374 | The default implementation of this method accepts a hash or hash reference of | ||||
375 | named parameters. If it receives a single argument that isn't a hash reference | ||||
376 | it throws an error. | ||||
377 | |||||
378 | You can override this method in your class to handle other types of options | ||||
379 | passed to the constructor. | ||||
380 | |||||
381 | This method should always return a hash reference of named options. | ||||
382 | |||||
383 | =head2 FOREIGNBUILDARGS | ||||
384 | |||||
385 | If you are inheriting from a non-Moo class, the arguments passed to the parent | ||||
386 | class constructor can be manipulated by defining a C<FOREIGNBUILDARGS> method. | ||||
387 | It will receive the same arguments as C<BUILDARGS>, and should return a list | ||||
388 | of arguments to pass to the parent class constructor. | ||||
389 | |||||
390 | =head2 BUILD | ||||
391 | |||||
392 | Define a C<BUILD> method on your class and the constructor will automatically | ||||
393 | call the C<BUILD> method from parent down to child after the object has | ||||
394 | been instantiated. Typically this is used for object validation or possibly | ||||
395 | logging. | ||||
396 | |||||
397 | =head2 DEMOLISH | ||||
398 | |||||
399 | If you have a C<DEMOLISH> method anywhere in your inheritance hierarchy, | ||||
400 | a C<DESTROY> method is created on first object construction which will call | ||||
401 | C<< $instance->DEMOLISH($in_global_destruction) >> for each C<DEMOLISH> | ||||
402 | method from child upwards to parents. | ||||
403 | |||||
404 | Note that the C<DESTROY> method is created on first construction of an object | ||||
405 | of your class in order to not add overhead to classes without C<DEMOLISH> | ||||
406 | methods; this may prove slightly surprising if you try and define your own. | ||||
407 | |||||
408 | =head2 does | ||||
409 | |||||
410 | if ($foo->does('Some::Role1')) { | ||||
411 | ... | ||||
412 | } | ||||
413 | |||||
414 | Returns true if the object composes in the passed role. | ||||
415 | |||||
416 | =head1 IMPORTED SUBROUTINES | ||||
417 | |||||
418 | =head2 extends | ||||
419 | |||||
420 | extends 'Parent::Class'; | ||||
421 | |||||
422 | Declares base class. Multiple superclasses can be passed for multiple | ||||
423 | inheritance (but please use roles instead). | ||||
424 | |||||
425 | Calling extends more than once will REPLACE your superclasses, not add to | ||||
426 | them like 'use base' would. | ||||
427 | |||||
428 | =head2 with | ||||
429 | |||||
430 | with 'Some::Role1'; | ||||
431 | |||||
432 | or | ||||
433 | |||||
434 | with 'Some::Role1', 'Some::Role2'; | ||||
435 | |||||
436 | Composes one or more L<Moo::Role> (or L<Role::Tiny>) roles into the current | ||||
437 | class. An error will be raised if these roles have conflicting methods. | ||||
438 | |||||
439 | =head2 has | ||||
440 | |||||
441 | has attr => ( | ||||
442 | is => 'ro', | ||||
443 | ); | ||||
444 | |||||
445 | Declares an attribute for the class. | ||||
446 | |||||
447 | package Foo; | ||||
448 | use Moo; | ||||
449 | has 'attr' => ( | ||||
450 | is => 'ro' | ||||
451 | ); | ||||
452 | |||||
453 | package Bar; | ||||
454 | use Moo; | ||||
455 | extends 'Foo'; | ||||
456 | has '+attr' => ( | ||||
457 | default => sub { "blah" }, | ||||
458 | ); | ||||
459 | |||||
460 | Using the C<+> notation, it's possible to override an attribute. | ||||
461 | |||||
462 | The options for C<has> are as follows: | ||||
463 | |||||
464 | =over 2 | ||||
465 | |||||
466 | =item * is | ||||
467 | |||||
468 | B<required>, may be C<ro>, C<lazy>, C<rwp> or C<rw>. | ||||
469 | |||||
470 | C<ro> generates an accessor that dies if you attempt to write to it - i.e. | ||||
471 | a getter only - by defaulting C<reader> to the name of the attribute. | ||||
472 | |||||
473 | C<lazy> generates a reader like C<ro>, but also sets C<lazy> to 1 and | ||||
474 | C<builder> to C<_build_${attribute_name}> to allow on-demand generated | ||||
475 | attributes. This feature was my attempt to fix my incompetence when | ||||
476 | originally designing C<lazy_build>, and is also implemented by | ||||
477 | L<MooseX::AttributeShortcuts>. There is, however, nothing to stop you | ||||
478 | using C<lazy> and C<builder> yourself with C<rwp> or C<rw> - it's just that | ||||
479 | this isn't generally a good idea so we don't provide a shortcut for it. | ||||
480 | |||||
481 | C<rwp> generates a reader like C<ro>, but also sets C<writer> to | ||||
482 | C<_set_${attribute_name}> for attributes that are designed to be written | ||||
483 | from inside of the class, but read-only from outside. | ||||
484 | This feature comes from L<MooseX::AttributeShortcuts>. | ||||
485 | |||||
486 | C<rw> generates a normal getter/setter by defaulting C<accessor> to the | ||||
487 | name of the attribute. | ||||
488 | |||||
489 | =item * isa | ||||
490 | |||||
491 | Takes a coderef which is meant to validate the attribute. Unlike L<Moose>, Moo | ||||
492 | does not include a basic type system, so instead of doing C<< isa => 'Num' >>, | ||||
493 | one should do | ||||
494 | |||||
495 | isa => sub { | ||||
496 | die "$_[0] is not a number!" unless looks_like_number $_[0] | ||||
497 | }, | ||||
498 | |||||
499 | Note that the return value is ignored, only whether the sub lives or | ||||
500 | dies matters. | ||||
501 | |||||
502 | L<Sub::Quote aware|/SUB QUOTE AWARE> | ||||
503 | |||||
504 | Since L<Moo> does B<not> run the C<isa> check before C<coerce> if a coercion | ||||
505 | subroutine has been supplied, C<isa> checks are not structural to your code | ||||
506 | and can, if desired, be omitted on non-debug builds (although if this results | ||||
507 | in an uncaught bug causing your program to break, the L<Moo> authors guarantee | ||||
508 | nothing except that you get to keep both halves). | ||||
509 | |||||
510 | If you want L<MooseX::Types> style named types, look at | ||||
511 | L<MooX::Types::MooseLike>. | ||||
512 | |||||
513 | To cause your C<isa> entries to be automatically mapped to named | ||||
514 | L<Moose::Meta::TypeConstraint> objects (rather than the default behaviour | ||||
515 | of creating an anonymous type), set: | ||||
516 | |||||
517 | $Moo::HandleMoose::TYPE_MAP{$isa_coderef} = sub { | ||||
518 | require MooseX::Types::Something; | ||||
519 | return MooseX::Types::Something::TypeName(); | ||||
520 | }; | ||||
521 | |||||
522 | Note that this example is purely illustrative; anything that returns a | ||||
523 | L<Moose::Meta::TypeConstraint> object or something similar enough to it to | ||||
524 | make L<Moose> happy is fine. | ||||
525 | |||||
526 | =item * coerce | ||||
527 | |||||
528 | Takes a coderef which is meant to coerce the attribute. The basic idea is to | ||||
529 | do something like the following: | ||||
530 | |||||
531 | coerce => sub { | ||||
532 | $_[0] % 2 ? $_[0] : $_[0] + 1 | ||||
533 | }, | ||||
534 | |||||
535 | Note that L<Moo> will always fire your coercion: this is to permit | ||||
536 | C<isa> entries to be used purely for bug trapping, whereas coercions are | ||||
537 | always structural to your code. We do, however, apply any supplied C<isa> | ||||
538 | check after the coercion has run to ensure that it returned a valid value. | ||||
539 | |||||
540 | L<Sub::Quote aware|/SUB QUOTE AWARE> | ||||
541 | |||||
542 | =item * handles | ||||
543 | |||||
544 | Takes a string | ||||
545 | |||||
546 | handles => 'RobotRole' | ||||
547 | |||||
548 | Where C<RobotRole> is a role (L<Moo::Role>) that defines an interface which | ||||
549 | becomes the list of methods to handle. | ||||
550 | |||||
551 | Takes a list of methods | ||||
552 | |||||
553 | handles => [ qw( one two ) ] | ||||
554 | |||||
555 | Takes a hashref | ||||
556 | |||||
557 | handles => { | ||||
558 | un => 'one', | ||||
559 | } | ||||
560 | |||||
561 | =item * C<trigger> | ||||
562 | |||||
563 | Takes a coderef which will get called any time the attribute is set. This | ||||
564 | includes the constructor, but not default or built values. Coderef will be | ||||
565 | invoked against the object with the new value as an argument. | ||||
566 | |||||
567 | If you set this to just C<1>, it generates a trigger which calls the | ||||
568 | C<_trigger_${attr_name}> method on C<$self>. This feature comes from | ||||
569 | L<MooseX::AttributeShortcuts>. | ||||
570 | |||||
571 | Note that Moose also passes the old value, if any; this feature is not yet | ||||
572 | supported. | ||||
573 | |||||
574 | L<Sub::Quote aware|/SUB QUOTE AWARE> | ||||
575 | |||||
576 | =item * C<default> | ||||
577 | |||||
578 | Takes a coderef which will get called with $self as its only argument | ||||
579 | to populate an attribute if no value is supplied to the constructor - or | ||||
580 | if the attribute is lazy, when the attribute is first retrieved if no | ||||
581 | value has yet been provided. | ||||
582 | |||||
583 | If a simple scalar is provided, it will be inlined as a string. Any non-code | ||||
584 | reference (hash, array) will result in an error - for that case instead use | ||||
585 | a code reference that returns the desired value. | ||||
586 | |||||
587 | Note that if your default is fired during new() there is no guarantee that | ||||
588 | other attributes have been populated yet so you should not rely on their | ||||
589 | existence. | ||||
590 | |||||
591 | L<Sub::Quote aware|/SUB QUOTE AWARE> | ||||
592 | |||||
593 | =item * C<predicate> | ||||
594 | |||||
595 | Takes a method name which will return true if an attribute has a value. | ||||
596 | |||||
597 | If you set this to just C<1>, the predicate is automatically named | ||||
598 | C<has_${attr_name}> if your attribute's name does not start with an | ||||
599 | underscore, or C<_has_${attr_name_without_the_underscore}> if it does. | ||||
600 | This feature comes from L<MooseX::AttributeShortcuts>. | ||||
601 | |||||
602 | =item * C<builder> | ||||
603 | |||||
604 | Takes a method name which will be called to create the attribute - functions | ||||
605 | exactly like default except that instead of calling | ||||
606 | |||||
607 | $default->($self); | ||||
608 | |||||
609 | Moo will call | ||||
610 | |||||
611 | $self->$builder; | ||||
612 | |||||
613 | The following features come from L<MooseX::AttributeShortcuts>: | ||||
614 | |||||
615 | If you set this to just C<1>, the builder is automatically named | ||||
616 | C<_build_${attr_name}>. | ||||
617 | |||||
618 | If you set this to a coderef or code-convertible object, that variable will be | ||||
619 | installed under C<$class::_build_${attr_name}> and the builder set to the same | ||||
620 | name. | ||||
621 | |||||
622 | =item * C<clearer> | ||||
623 | |||||
624 | Takes a method name which will clear the attribute. | ||||
625 | |||||
626 | If you set this to just C<1>, the clearer is automatically named | ||||
627 | C<clear_${attr_name}> if your attribute's name does not start with an | ||||
628 | underscore, or <_clear_${attr_name_without_the_underscore}> if it does. | ||||
629 | This feature comes from L<MooseX::AttributeShortcuts>. | ||||
630 | |||||
631 | =item * C<lazy> | ||||
632 | |||||
633 | B<Boolean>. Set this if you want values for the attribute to be grabbed | ||||
634 | lazily. This is usually a good idea if you have a L</builder> which requires | ||||
635 | another attribute to be set. | ||||
636 | |||||
637 | =item * C<required> | ||||
638 | |||||
639 | B<Boolean>. Set this if the attribute must be passed on instantiation. | ||||
640 | |||||
641 | =item * C<reader> | ||||
642 | |||||
643 | The value of this attribute will be the name of the method to get the value of | ||||
644 | the attribute. If you like Java style methods, you might set this to | ||||
645 | C<get_foo> | ||||
646 | |||||
647 | =item * C<writer> | ||||
648 | |||||
649 | The value of this attribute will be the name of the method to set the value of | ||||
650 | the attribute. If you like Java style methods, you might set this to | ||||
651 | C<set_foo>. | ||||
652 | |||||
653 | =item * C<weak_ref> | ||||
654 | |||||
655 | B<Boolean>. Set this if you want the reference that the attribute contains to | ||||
656 | be weakened; use this when circular references are possible, which will cause | ||||
657 | leaks. | ||||
658 | |||||
659 | =item * C<init_arg> | ||||
660 | |||||
661 | Takes the name of the key to look for at instantiation time of the object. A | ||||
662 | common use of this is to make an underscored attribute have a non-underscored | ||||
663 | initialization name. C<undef> means that passing the value in on instantiation | ||||
664 | is ignored. | ||||
665 | |||||
666 | =item * C<moosify> | ||||
667 | |||||
668 | Takes either a coderef or array of coderefs which is meant to transform the | ||||
669 | given attributes specifications if necessary when upgrading to a Moose role or | ||||
670 | class. You shouldn't need this by default, but is provided as a means of | ||||
671 | possible extensibility. | ||||
672 | |||||
673 | =back | ||||
674 | |||||
675 | =head2 before | ||||
676 | |||||
677 | before foo => sub { ... }; | ||||
678 | |||||
679 | See L<< Class::Method::Modifiers/before method(s) => sub { ... } >> for full | ||||
680 | documentation. | ||||
681 | |||||
682 | =head2 around | ||||
683 | |||||
684 | around foo => sub { ... }; | ||||
685 | |||||
686 | See L<< Class::Method::Modifiers/around method(s) => sub { ... } >> for full | ||||
687 | documentation. | ||||
688 | |||||
689 | =head2 after | ||||
690 | |||||
691 | after foo => sub { ... }; | ||||
692 | |||||
693 | See L<< Class::Method::Modifiers/after method(s) => sub { ... } >> for full | ||||
694 | documentation. | ||||
695 | |||||
696 | =head1 SUB QUOTE AWARE | ||||
697 | |||||
698 | L<Sub::Quote/quote_sub> allows us to create coderefs that are "inlineable," | ||||
699 | giving us a handy, XS-free speed boost. Any option that is L<Sub::Quote> | ||||
700 | aware can take advantage of this. | ||||
701 | |||||
702 | To do this, you can write | ||||
703 | |||||
704 | use Moo; | ||||
705 | use Sub::Quote; | ||||
706 | |||||
707 | has foo => ( | ||||
708 | is => 'ro', | ||||
709 | isa => quote_sub(q{ die "Not <3" unless $_[0] < 3 }) | ||||
710 | ); | ||||
711 | |||||
712 | which will be inlined as | ||||
713 | |||||
714 | do { | ||||
715 | local @_ = ($_[0]->{foo}); | ||||
716 | die "Not <3" unless $_[0] < 3; | ||||
717 | } | ||||
718 | |||||
719 | or to avoid localizing @_, | ||||
720 | |||||
721 | has foo => ( | ||||
722 | is => 'ro', | ||||
723 | isa => quote_sub(q{ my ($val) = @_; die "Not <3" unless $val < 3 }) | ||||
724 | ); | ||||
725 | |||||
726 | which will be inlined as | ||||
727 | |||||
728 | do { | ||||
729 | my ($val) = ($_[0]->{foo}); | ||||
730 | die "Not <3" unless $val < 3; | ||||
731 | } | ||||
732 | |||||
733 | See L<Sub::Quote> for more information, including how to pass lexical | ||||
734 | captures that will also be compiled into the subroutine. | ||||
735 | |||||
736 | =head1 INCOMPATIBILITIES WITH MOOSE | ||||
737 | |||||
738 | There is no built-in type system. C<isa> is verified with a coderef; if you | ||||
739 | need complex types, just make a library of coderefs, or better yet, functions | ||||
740 | that return quoted subs. L<MooX::Types::MooseLike> provides a similar API | ||||
741 | to L<MooseX::Types::Moose> so that you can write | ||||
742 | |||||
743 | has days_to_live => (is => 'ro', isa => Int); | ||||
744 | |||||
745 | and have it work with both; it is hoped that providing only subrefs as an | ||||
746 | API will encourage the use of other type systems as well, since it's | ||||
747 | probably the weakest part of Moose design-wise. | ||||
748 | |||||
749 | C<initializer> is not supported in core since the author considers it to be a | ||||
750 | bad idea and Moose best practices recommend avoiding it. Meanwhile C<trigger> or | ||||
751 | C<coerce> are more likely to be able to fulfill your needs. | ||||
752 | |||||
753 | There is no meta object. If you need this level of complexity you wanted | ||||
754 | L<Moose> - Moo succeeds at being small because it explicitly does not | ||||
755 | provide a metaprotocol. However, if you load L<Moose>, then | ||||
756 | |||||
757 | Class::MOP::class_of($moo_class_or_role) | ||||
758 | |||||
759 | will return an appropriate metaclass pre-populated by L<Moo>. | ||||
760 | |||||
761 | No support for C<super>, C<override>, C<inner>, or C<augment> - the author | ||||
762 | considers augment to be a bad idea, and override can be translated: | ||||
763 | |||||
764 | override foo => sub { | ||||
765 | ... | ||||
766 | super(); | ||||
767 | ... | ||||
768 | }; | ||||
769 | |||||
770 | around foo => sub { | ||||
771 | my ($orig, $self) = (shift, shift); | ||||
772 | ... | ||||
773 | $self->$orig(@_); | ||||
774 | ... | ||||
775 | }; | ||||
776 | |||||
777 | The C<dump> method is not provided by default. The author suggests loading | ||||
778 | L<Devel::Dwarn> into C<main::> (via C<perl -MDevel::Dwarn ...> for example) and | ||||
779 | using C<$obj-E<gt>$::Dwarn()> instead. | ||||
780 | |||||
781 | L</default> only supports coderefs and plain scalars, because passing a hash | ||||
782 | or array reference as a default is almost always incorrect since the value is | ||||
783 | then shared between all objects using that default. | ||||
784 | |||||
785 | C<lazy_build> is not supported; you are instead encouraged to use the | ||||
786 | C<< is => 'lazy' >> option supported by L<Moo> and L<MooseX::AttributeShortcuts>. | ||||
787 | |||||
788 | C<auto_deref> is not supported since the author considers it a bad idea and | ||||
789 | it has been considered best practice to avoid it for some time. | ||||
790 | |||||
791 | C<documentation> will show up in a L<Moose> metaclass created from your class | ||||
792 | but is otherwise ignored. Then again, L<Moose> ignores it as well, so this | ||||
793 | is arguably not an incompatibility. | ||||
794 | |||||
795 | Since C<coerce> does not require C<isa> to be defined but L<Moose> does | ||||
796 | require it, the metaclass inflation for coerce alone is a trifle insane | ||||
797 | and if you attempt to subtype the result will almost certainly break. | ||||
798 | |||||
799 | Handling of warnings: when you C<use Moo> we enable FATAL warnings. The nearest | ||||
800 | similar invocation for L<Moose> would be: | ||||
801 | |||||
802 | use Moose; | ||||
803 | use warnings FATAL => "all"; | ||||
804 | |||||
805 | Additionally, L<Moo> supports a set of attribute option shortcuts intended to | ||||
806 | reduce common boilerplate. The set of shortcuts is the same as in the L<Moose> | ||||
807 | module L<MooseX::AttributeShortcuts> as of its version 0.009+. So if you: | ||||
808 | |||||
809 | package MyClass; | ||||
810 | use Moo; | ||||
811 | |||||
812 | The nearest L<Moose> invocation would be: | ||||
813 | |||||
814 | package MyClass; | ||||
815 | |||||
816 | use Moose; | ||||
817 | use warnings FATAL => "all"; | ||||
818 | use MooseX::AttributeShortcuts; | ||||
819 | |||||
820 | or, if you're inheriting from a non-Moose class, | ||||
821 | |||||
822 | package MyClass; | ||||
823 | |||||
824 | use Moose; | ||||
825 | use MooseX::NonMoose; | ||||
826 | use warnings FATAL => "all"; | ||||
827 | use MooseX::AttributeShortcuts; | ||||
828 | |||||
829 | Finally, Moose requires you to call | ||||
830 | |||||
831 | __PACKAGE__->meta->make_immutable; | ||||
832 | |||||
833 | at the end of your class to get an inlined (i.e. not horribly slow) | ||||
834 | constructor. Moo does it automatically the first time ->new is called | ||||
835 | on your class. (C<make_immutable> is a no-op in Moo to ease migration.) | ||||
836 | |||||
837 | An extension L<MooX::late> exists to ease translating Moose packages | ||||
838 | to Moo by providing a more Moose-like interface. | ||||
839 | |||||
840 | =head1 SUPPORT | ||||
841 | |||||
842 | Users' IRC: #moose on irc.perl.org | ||||
843 | |||||
844 | =for html <a href="http://chat.mibbit.com/#moose@irc.perl.org">(click for instant chatroom login)</a> | ||||
845 | |||||
846 | Development and contribution IRC: #web-simple on irc.perl.org | ||||
847 | |||||
848 | =for html <a href="http://chat.mibbit.com/#web-simple@irc.perl.org">(click for instant chatroom login)</a> | ||||
849 | |||||
850 | Bugtracker: L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Moo> | ||||
851 | |||||
852 | Git repository: L<git://git.shadowcat.co.uk/gitmo/Moo.git> | ||||
853 | |||||
854 | Git web access: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo/Moo.git> | ||||
855 | |||||
856 | =head1 AUTHOR | ||||
857 | |||||
858 | mst - Matt S. Trout (cpan:MSTROUT) <mst@shadowcat.co.uk> | ||||
859 | |||||
860 | =head1 CONTRIBUTORS | ||||
861 | |||||
862 | dg - David Leadbeater (cpan:DGL) <dgl@dgl.cx> | ||||
863 | |||||
864 | frew - Arthur Axel "fREW" Schmidt (cpan:FREW) <frioux@gmail.com> | ||||
865 | |||||
866 | hobbs - Andrew Rodland (cpan:ARODLAND) <arodland@cpan.org> | ||||
867 | |||||
868 | jnap - John Napiorkowski (cpan:JJNAPIORK) <jjn1056@yahoo.com> | ||||
869 | |||||
870 | ribasushi - Peter Rabbitson (cpan:RIBASUSHI) <ribasushi@cpan.org> | ||||
871 | |||||
872 | chip - Chip Salzenberg (cpan:CHIPS) <chip@pobox.com> | ||||
873 | |||||
874 | ajgb - Alex J. G. Burzyński (cpan:AJGB) <ajgb@cpan.org> | ||||
875 | |||||
876 | doy - Jesse Luehrs (cpan:DOY) <doy at tozt dot net> | ||||
877 | |||||
878 | perigrin - Chris Prather (cpan:PERIGRIN) <chris@prather.org> | ||||
879 | |||||
880 | Mithaldu - Christian Walde (cpan:MITHALDU) <walde.christian@googlemail.com> | ||||
881 | |||||
882 | ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) <ilmari@ilmari.org> | ||||
883 | |||||
884 | tobyink - Toby Inkster (cpan:TOBYINK) <tobyink@cpan.org> | ||||
885 | |||||
886 | haarg - Graham Knop (cpan:HAARG) <haarg@cpan.org> | ||||
887 | |||||
888 | mattp - Matt Phillips (cpan:MATTP) <mattp@cpan.org> | ||||
889 | |||||
890 | =head1 COPYRIGHT | ||||
891 | |||||
892 | Copyright (c) 2010-2011 the Moo L</AUTHOR> and L</CONTRIBUTORS> | ||||
893 | as listed above. | ||||
894 | |||||
895 | =head1 LICENSE | ||||
896 | |||||
897 | This library is free software and may be distributed under the same terms | ||||
898 | as perl itself. See L<http://dev.perl.org/licenses/>. | ||||
899 | |||||
900 | =cut |