rewrite nonMoo detection
[gitmo/Moo.git] / lib / Moo.pm
1 package Moo;
2
3 use strictures 1;
4 use Moo::_Utils;
5
6 our $VERSION = '0.009004'; # 0.9.4
7 $VERSION = eval $VERSION;
8
9 our %MAKERS;
10
11 sub import {
12   my $target = caller;
13   my $class = shift;
14   strictures->import;
15   return if $MAKERS{$target}; # already exported into this package
16   *{_getglob("${target}::extends")} = sub {
17     _load_module($_) for @_;
18     # Can't do *{...} = \@_ or 5.10.0's mro.pm stops seeing @ISA
19     @{*{_getglob("${target}::ISA")}{ARRAY}} = @_;
20   };
21   *{_getglob("${target}::with")} = sub {
22     require Moo::Role;
23     die "Only one role supported at a time by with" if @_ > 1;
24     Moo::Role->apply_role_to_package($target, $_[0]);
25   };
26   $MAKERS{$target} = {};
27   *{_getglob("${target}::has")} = sub {
28     my ($name, %spec) = @_;
29     ($MAKERS{$target}{accessor} ||= do {
30       require Method::Generate::Accessor;
31       Method::Generate::Accessor->new
32     })->generate_method($target, $name, \%spec);
33     $class->_constructor_maker_for($target)
34           ->register_attribute_specs($name, \%spec);
35   };
36   foreach my $type (qw(before after around)) {
37     *{_getglob "${target}::${type}"} = sub {
38       require Class::Method::Modifiers;
39       _install_modifier($target, $type, @_);
40     };
41   }
42   {
43     no strict 'refs';
44     @{"${target}::ISA"} = do {
45       require Moo::Object; ('Moo::Object');
46     } unless @{"${target}::ISA"};
47   }
48 }
49
50 sub _constructor_maker_for {
51   my ($class, $target, $select_super) = @_;
52   return unless $MAKERS{$target};
53   $MAKERS{$target}{constructor} ||= do {
54     require Method::Generate::Constructor;
55     require Sub::Defer;
56     my ($moo_constructor, $con);
57
58     if ($select_super && $MAKERS{$select_super}) {
59       $moo_constructor = 1;
60       $con = $MAKERS{$select_super}{constructor};
61     } else {
62       my $t_new = $target->can('new');
63       if ($t_new) {
64         if ($t_new == Moo::Object->can('new')) {
65           $moo_constructor = 1;
66         } elsif (my $defer_target = (Sub::Defer::defer_info($t_new)||[])->[0]) {
67           my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/);
68           if ($MAKERS{$pkg}) {
69             $moo_constructor = 1;
70             $con = $MAKERS{$pkg}{constructor};
71           }
72         }
73       } else {
74         $moo_constructor = 1; # no other constructor, make a Moo one
75       }
76     };
77     require Moo::_mro unless $moo_constructor;
78     Method::Generate::Constructor
79       ->new(
80         package => $target,
81         accessor_generator => do {
82           require Method::Generate::Accessor;
83           Method::Generate::Accessor->new;
84         },
85         ($moo_constructor ? ()
86           : (construction_string => '$class->next::method(@_)'))
87       )
88       ->install_delayed
89       ->register_attribute_specs(%{$con?$con->all_attribute_specs:{}})
90   }
91 }
92
93 1;
94
95 =head1 NAME
96
97 Moo - Minimalist Object Orientation (with Moose compatiblity)
98
99 =head1 WARNING WARNING WARNING
100
101 This is a 0.9 release because we're fairly sure it works. For us. Until it's
102 tested in the wild, we make no guarantees it also works for you.
103
104 If this module does something unexpected, please submit a failing test.
105
106 But if it eats your cat, sleeps with your boyfriend, or pushes grandma down
107 the stairs to save her from the terrible secret of space, it's not our fault.
108
109 =head1 SYNOPSIS
110
111  package Cat::Food;
112
113  use Moo;
114  use Sub::Quote;
115
116  sub feed_lion {
117    my $self = shift;
118    my $amount = shift || 1;
119
120    $self->pounds( $self->pounds - $amount );
121  }
122
123  has taste => (
124    is => 'ro',
125  );
126
127  has brand => (
128    is  => 'ro',
129    isa => sub {
130      die "Only SWEET-TREATZ supported!" unless $_[0] eq 'SWEET-TREATZ'
131    },
132 );
133
134  has pounds => (
135    is  => 'rw',
136    isa => quote_sub q{ die "$_[0] is too much cat food!" unless $_[0] < 15 },
137  );
138
139  1;
140
141 and else where
142
143  my $full = Cat::Food->new(
144     taste  => 'DELICIOUS.',
145     brand  => 'SWEET-TREATZ',
146     pounds => 10,
147  );
148
149  $full->feed_lion;
150
151  say $full->pounds;
152
153 =head1 DESCRIPTION
154
155 This module is an extremely light-weight, high-performance L<Moose> replacement.
156 It also avoids depending on any XS modules to allow simple deployments.  The
157 name C<Moo> is based on the idea that it provides almost -but not quite- two
158 thirds of L<Moose>.
159
160 Unlike C<Mouse> this module does not aim at full L<Moose> compatibility.  See
161 L</INCOMPATIBILITIES> for more details.
162
163 =head1 WHY MOO EXISTS
164
165 If you want a full object system with a rich Metaprotocol, L<Moose> is
166 already wonderful.
167
168 I've tried several times to use L<Mouse> but it's 3x the size of Moo and
169 takes longer to load than most of my Moo based CGI scripts take to run.
170
171 If you don't want L<Moose>, you don't want "less metaprotocol" like L<Mouse>,
172 you want "as little as possible" - which means "no metaprotocol", which is
173 what Moo provides.
174
175 By Moo 1.0 I intend to have Moo's equivalent of L<Any::Moose> built in -
176 if Moose gets loaded, any Moo class or role will act as a Moose equivalent
177 if treated as such.
178
179 Hence - Moo exists as its name - Minimal Object Orientation - with a pledge
180 to make it smooth to upgrade to L<Moose> when you need more than minimal
181 features.
182
183 =head1 IMPORTED METHODS
184
185 =head2 new
186
187  Foo::Bar->new( attr1 => 3 );
188
189 or
190
191  Foo::Bar->new({ attr1 => 3 });
192
193 =head2 BUILDARGS
194
195 This feature from Moose is not yet supported.
196
197 =head2 BUILDALL
198
199 Don't override (or probably even call) this method.  Instead, you can define
200 a C<BUILD> method on your class and the constructor will automatically call the
201 C<BUILD> method from parent down to child after the object has been
202 instantiated.  Typically this is used for object validation or possibly logging.
203
204 =head2 does
205
206  if ($foo->does('Some::Role1')) {
207    ...
208  }
209
210 Returns true if the object composes in the passed role.
211
212 =head1 IMPORTED SUBROUTINES
213
214 =head2 extends
215
216  extends 'Parent::Class';
217
218 Declares base class. Multiple superclasses can be passed for multiple
219 inheritance (but please use roles instead).
220
221 Calling extends more than once will REPLACE your superclasses, not add to
222 them like 'use base' would.
223
224 =head2 with
225
226  with 'Some::Role1';
227  with 'Some::Role2';
228
229 Composes a L<Role::Tiny> into current class.  Only one role may be composed in
230 at a time to allow the code to remain as simple as possible.
231
232 =head2 has
233
234  has attr => (
235    is => 'ro',
236  );
237
238 Declares an attribute for the class.
239
240 The options for C<has> are as follows:
241
242 =over 2
243
244 =item * is
245
246 B<required>, must be C<ro> or C<rw>.  Unsurprisingly, C<ro> generates an
247 accessor that will not respond to arguments; to be clear: a getter only. C<rw>
248 will create a perlish getter/setter.
249
250 =item * isa
251
252 Takes a coderef which is meant to validate the attribute.  Unlike L<Moose> Moo
253 does not include a basic type system, so instead of doing C<< isa => 'Num' >>,
254 one should do
255
256  isa => quote_sub q{
257    die "$_[0] is not a number!" unless looks_like_number $_[0]
258  },
259
260 L<Sub::Quote aware|/SUB QUOTE AWARE>
261
262 =item * coerce
263
264 This Moose feature is not yet supported
265
266 =begin hide
267
268 Takes a coderef which is meant to coerce the attribute.  The basic idea is to
269 do something like the following:
270
271  coerce => quote_sub q{
272    $_[0] + 1 unless $_[0] % 2
273  },
274
275 L<Sub::Quote aware|/SUB QUOTE AWARE>
276
277 =end hide
278
279 =item * trigger
280
281 Takes a coderef which will get called any time the attribute is set. Coderef
282 will be invoked against the object with the new value as an argument.
283
284 Note that Moose also passes the old value, if any; this feature is not yet
285 supported.
286
287 L<Sub::Quote aware|/SUB QUOTE AWARE>
288
289 =item * default
290
291 Takes a coderef which will get called with $self as its only argument
292 to populate an attribute if no value is supplied to the constructor - or
293 if the attribute is lazy, when the attribute is first retrieved if no
294 value has yet been provided.
295
296 Note that if your default is fired during new() there is no guarantee that
297 other attributes have been populated yet so you should not rely on their
298 existence.
299
300 L<Sub::Quote aware|/SUB QUOTE AWARE>
301
302 =item * predicate
303
304 Takes a method name which will return true if an attribute has a value.
305
306 A common example of this would be to call it C<has_$foo>, implying that the
307 object has a C<$foo> set.
308
309 =item * builder
310
311 Takes a method name which will be called to create the attribute - functions
312 exactly like default except that instead of calling
313
314   $default->($self);
315
316 Moo will call
317
318   $self->$builder;
319
320 =item * clearer
321
322 Takes a method name which will clear the attribute.
323
324 =item * lazy
325
326 B<Boolean>.  Set this if you want values for the attribute to be grabbed
327 lazily.  This is usually a good idea if you have a L</builder> which requires
328 another attribute to be set.
329
330 =item * required
331
332 B<Boolean>.  Set this if the attribute must be passed on instantiation.
333
334 =item * weak_ref
335
336 B<Boolean>.  Set this if you want the reference that the attribute contains to
337 be weakened; use this when circular references are possible, which will cause
338 leaks.
339
340 =item * init_arg
341
342 Takes the name of the key to look for at instantiation time of the object.  A
343 common use of this is to make an underscored attribute have a non-underscored
344 initialization name. C<undef> means that passing the value in on instantiation
345
346 =back
347
348 =head2 before
349
350  before foo => sub { ... };
351
352 See L<< Class::Method::Modifiers/before method(s) => sub { ... } >> for full
353 documentation.
354
355 =head2 around
356
357  around foo => sub { ... };
358
359 See L<< Class::Method::Modifiers/around method(s) => sub { ... } >> for full
360 documentation.
361
362 =head2 after
363
364  after foo => sub { ... };
365
366 See L<< Class::Method::Modifiers/after method(s) => sub { ... } >> for full
367 documentation.
368
369 =head1 SUB QUOTE AWARE
370
371 L<Sub::Quote/quote_sub> allows us to create coderefs that are "inlineable,"
372 giving us a handy, XS-free speed boost.  Any option that is L<Sub::Quote>
373 aware can take advantage of this.
374
375 =head1 INCOMPATIBILITIES WITH MOOSE
376
377 You can only compose one role at a time.  If your application is large or
378 complex enough to warrant complex composition, you wanted L<Moose>.
379
380 There is no complex type system.  C<isa> is verified with a coderef, if you
381 need complex types, just make a library of coderefs, or better yet, functions
382 that return quoted subs.
383
384 C<initializer> is not supported in core since the author considers it to be a
385 bad idea but may be supported by an extension in future.
386
387 There is no meta object.  If you need this level of complexity you wanted
388 L<Moose> - Moo succeeds at being small because it explicitly does not
389 provide a metaprotocol.
390
391 No support for C<super>, C<override>, C<inner>, or C<augment> - override can
392 be handled by around albeit with a little more typing, and the author considers
393 augment to be a bad idea.
394
395 L</default> only supports coderefs, because doing otherwise is usually a
396 mistake anyway.
397
398 C<lazy_build> is not supported per se, but of course it will work if you
399 manually set all the options it implies.
400
401 C<auto_deref> is not supported since the author considers it a bad idea.
402
403 C<documentation> is not supported since it's a very poor replacement for POD.