Use Class::Method::Modifiers 1.00 for before/after/around
[gitmo/Mouse.git] / lib / Mouse.pm
CommitLineData
c3398f5b 1#!perl
2package Mouse;
3use strict;
4use warnings;
5
f8b285d2 6our $VERSION = '0.02';
126765f0 7use 5.006;
c3398f5b 8
9use Sub::Exporter;
10use Carp 'confess';
11use Scalar::Util 'blessed';
8517d2ff 12use Class::Method::Modifiers ();
c3398f5b 13
306290e8 14use Mouse::Meta::Attribute;
15use Mouse::Meta::Class;
c3398f5b 16use Mouse::Object;
d60c78b9 17use Mouse::TypeRegistry;
c3398f5b 18
19do {
20 my $CALLER;
21
22 my %exports = (
23 meta => sub {
306290e8 24 my $meta = Mouse::Meta::Class->initialize($CALLER);
c3398f5b 25 return sub { $meta };
26 },
27
28 extends => sub {
29 my $caller = $CALLER;
30 return sub {
31 $caller->meta->superclasses(@_);
32 };
33 },
34
35 has => sub {
36 return sub {
37 my $package = caller;
38 my $names = shift;
39 $names = [$names] if !ref($names);
40
41 for my $name (@$names) {
306290e8 42 Mouse::Meta::Attribute->create($package, $name, @_);
c3398f5b 43 }
44 };
45 },
46
47 confess => sub {
b17094ce 48 return \&confess;
c3398f5b 49 },
50
51 blessed => sub {
b17094ce 52 return \&blessed;
c3398f5b 53 },
8517d2ff 54
55 before => sub {
56 return \&Class::Method::Modifiers::before;
57 },
58
59 after => sub {
60 return \&Class::Method::Modifiers::after;
61 },
62
63 around => sub {
64 return \&Class::Method::Modifiers::around;
65 },
c3398f5b 66 );
67
68 my $exporter = Sub::Exporter::build_exporter({
69 exports => \%exports,
70 groups => { default => [':all'] },
71 });
72
73 sub import {
74 $CALLER = caller;
75
76 strict->import;
77 warnings->import;
78
306290e8 79 my $meta = Mouse::Meta::Class->initialize($CALLER);
ca73a208 80 $meta->superclasses('Mouse::Object')
81 unless $meta->superclasses;
c3398f5b 82
83 goto $exporter;
84 }
85
86 sub unimport {
87 my $caller = caller;
88
89 no strict 'refs';
90 for my $keyword (keys %exports) {
91 next if $keyword eq 'meta'; # we don't delete this one
92 delete ${ $caller . '::' }{$keyword};
93 }
94 }
95};
96
97sub load_class {
98 my $class = shift;
262801ef 99
9694b71b 100 if (ref($class) || !defined($class) || !length($class)) {
101 my $display = defined($class) ? $class : 'undef';
102 confess "Invalid class name ($display)";
103 }
c3398f5b 104
2a674d23 105 return 1 if is_class_loaded($class);
106
c3398f5b 107 (my $file = "$class.pm") =~ s{::}{/}g;
108
109 eval { CORE::require($file) };
2a674d23 110 confess "Could not load class ($class) because : $@" if $@;
c3398f5b 111
112 return 1;
113}
114
2a674d23 115sub is_class_loaded {
116 my $class = shift;
117
7ecc2123 118 return 0 if ref($class) || !defined($class) || !length($class);
119
bf134049 120 # walk the symbol table tree to avoid autovififying
121 # \*{${main::}{"Foo::"}} == \*main::Foo::
122
123 my $pack = \*::;
124 foreach my $part (split('::', $class)) {
125 return 0 unless exists ${$$pack}{"${part}::"};
126 $pack = \*{${$$pack}{"${part}::"}};
2a674d23 127 }
bf134049 128
129 # check for $VERSION or @ISA
130 return 1 if exists ${$$pack}{VERSION}
131 && defined *{${$$pack}{VERSION}}{SCALAR};
132 return 1 if exists ${$$pack}{ISA}
133 && defined *{${$$pack}{ISA}}{ARRAY};
134
135 # check for any method
136 foreach ( keys %{$$pack} ) {
137 next if substr($_, -2, 2) eq '::';
138 return 1 if defined *{${$$pack}{$_}}{CODE};
139 }
140
141 # fail
2a674d23 142 return 0;
143}
144
c3398f5b 1451;
146
147__END__
148
149=head1 NAME
150
0fff36e6 151Mouse - Moose minus the antlers
c3398f5b 152
153=head1 VERSION
154
f8b285d2 155Version 0.02 released 11 Jun 08
c3398f5b 156
157=head1 SYNOPSIS
158
159 package Point;
6caea456 160 use Mouse; # automatically turns on strict and warnings
161
162 has 'x' => (is => 'rw', isa => 'Int');
163 has 'y' => (is => 'rw', isa => 'Int');
164
165 sub clear {
166 my $self = shift;
167 $self->x(0);
168 $self->y(0);
169 }
170
171 package Point3D;
c3398f5b 172 use Mouse;
173
6caea456 174 extends 'Point';
c3398f5b 175
6caea456 176 has 'z' => (is => 'rw', isa => 'Int');
177
8517d2ff 178 after 'clear' => sub {
179 my $self = shift;
180 $self->z(0);
181 };
c3398f5b 182
183=head1 DESCRIPTION
184
0fff36e6 185L<Moose> is wonderful.
c3398f5b 186
0fff36e6 187Unfortunately, it's a little slow. Though significant progress has been made
188over the years, the compile time penalty is a non-starter for some
189applications.
190
191Mouse aims to alleviate this by providing a subset of Moose's
192functionality, faster. In particular, L<Moose/has> is missing only a few
193expert-level features.
194
195=head2 MOOSE COMPAT
196
197Compatibility with Moose has been the utmost concern. Fewer than 1% of the
198tests fail when run against Moose instead of Mouse. Mouse code coverage is also
8e1a28a8 199over 99%. Even the error messages are taken from Moose. The Mouse code just
200runs the test suite 3x-4x faster.
0fff36e6 201
202The idea is that, if you need the extra power, you should be able to run
8e1a28a8 203C<s/Mouse/Moose/g> on your codebase and have nothing break. To that end,
204nothingmuch has written L<Squirrel> (part of this distribution) which will act
205as Mouse unless Moose is loaded, in which case it will act as Moose.
0fff36e6 206
207Mouse also has the blessings of Moose's author, stevan.
208
209=head2 MISSING FEATURES
210
211=head3 Method modifiers
212
dca275b5 213Fixing this one next, with a reimplementation of L<Class::Method::Modifiers>.
0fff36e6 214
215=head3 Roles
216
217Fixing this one slightly less soon. stevan has suggested an implementation
218strategy. Mouse currently mostly ignores methods.
219
220=head3 Complex types
221
222User-defined type constraints and parameterized types may be implemented. Type
223coercions probably not (patches welcome).
224
225=head3 Bootstrapped meta world
226
227Very handy for extensions to the MOP. Not pressing, but would be nice to have.
228
229=head3 Modification of attribute metaclass
230
231When you declare an attribute with L</has>, you get the inlined accessors
232installed immediately. Modifying the attribute metaclass, even if possible,
233does nothing.
234
235=head3 Lots more..
236
237MouseX?
238
239=head1 KEYWORDS
c3398f5b 240
306290e8 241=head2 meta -> Mouse::Meta::Class
c3398f5b 242
243Returns this class' metaclass instance.
244
245=head2 extends superclasses
246
247Sets this class' superclasses.
248
249=head2 has (name|names) => parameters
250
251Adds an attribute (or if passed an arrayref of names, multiple attributes) to
0fff36e6 252this class. Options:
253
254=over 4
255
256=item is => ro|rw
257
258If specified, inlines a read-only/read-write accessor with the same name as
259the attribute.
260
261=item isa => TypeConstraint
262
263Provides basic type checking in the constructor and accessor. Basic types such
264as C<Int>, C<ArrayRef>, C<Defined> are supported. Any unknown type is taken to
265be a class check (e.g. isa => 'DateTime' would accept only L<DateTime>
266objects).
267
268=item required => 0|1
269
270Whether this attribute is required to have a value. If the attribute is lazy or
271has a builder, then providing a value for the attribute in the constructor is
272optional.
273
274=item init_arg => Str
275
276Allows you to use a different key name in the constructor.
277
278=item default => Value | CodeRef
279
280Sets the default value of the attribute. If the default is a coderef, it will
281be invoked to get the default value. Due to quirks of Perl, any bare reference
282is forbidden, you must wrap the reference in a coderef. Otherwise, all
283instances will share the same reference.
284
285=item lazy => 0|1
286
287If specified, the default is calculated on demand instead of in the
288constructor.
289
290=item predicate => Str
291
292Lets you specify a method name for installing a predicate method, which checks
293that the attribute has a value. It will not invoke a lazy default or builder
294method.
295
296=item clearer => Str
297
298Lets you specify a method name for installing a clearer method, which clears
299the attribute's value from the instance. On the next read, lazy or builder will
300be invoked.
301
302=item handles => HashRef|ArrayRef
303
304Lets you specify methods to delegate to the attribute. ArrayRef forwards the
305given method names to method calls on the attribute. HashRef maps local method
306names to remote method names called on the attribute. Other forms of
307L</handles>, such as regular expression and coderef, are not yet supported.
308
309=item weak_ref => 0|1
310
311Lets you automatically weaken any reference stored in the attribute.
312
313=item trigger => Coderef
314
315Any time the attribute's value is set (either through the accessor or the
316constructor), the trigger is called on it. The trigger receives as arguments
317the instance, the new value, and the attribute instance.
318
319=item builder => Str
320
321Defines a method name to be called to provide the default value of the
322attribute. C<< builder => 'build_foo' >> is mostly equivalent to
323C<< default => sub { $_[0]->build_foo } >>.
324
325=item auto_deref => 0|1
326
327Allows you to automatically dereference ArrayRef and HashRef attributes in list
328context. In scalar context, the reference is returned (NOT the list length or
329bucket status). You must specify an appropriate type constraint to use
330auto_deref.
331
332=back
c3398f5b 333
334=head2 confess error -> BOOM
335
336L<Carp/confess> for your convenience.
337
338=head2 blessed value -> ClassName | undef
339
340L<Scalar::Util/blessed> for your convenience.
341
342=head1 MISC
343
344=head2 import
345
6caea456 346Importing Mouse will default your class' superclass list to L<Mouse::Object>.
c3398f5b 347You may use L</extends> to replace the superclass list.
348
349=head2 unimport
350
0fff36e6 351Please unimport Mouse (C<no Mouse>) so that if someone calls one of the
352keywords (such as L</extends>) it will break loudly instead breaking subtly.
c3398f5b 353
354=head1 FUNCTIONS
355
356=head2 load_class Class::Name
357
6caea456 358This will load a given C<Class::Name> (or die if it's not loadable).
c3398f5b 359This function can be used in place of tricks like
360C<eval "use $module"> or using C<require>.
361
262801ef 362=head2 is_class_loaded Class::Name -> Bool
363
364Returns whether this class is actually loaded or not. It uses a heuristic which
365involves checking for the existence of C<$VERSION>, C<@ISA>, and any
366locally-defined method.
367
c3398f5b 368=head1 AUTHOR
369
370Shawn M Moore, C<< <sartak at gmail.com> >>
371
0fff36e6 372with plenty of code borrowed from L<Class::MOP> and L<Moose>
373
c3398f5b 374=head1 BUGS
375
376No known bugs.
377
378Please report any bugs through RT: email
379C<bug-mouse at rt.cpan.org>, or browse
380L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Mouse>.
381
382=head1 COPYRIGHT AND LICENSE
383
384Copyright 2008 Shawn M Moore.
385
386This program is free software; you can redistribute it and/or modify it
387under the same terms as Perl itself.
388
389=cut
390