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