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