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