package Mouse;
use strict;
use warnings;
+use base 'Exporter';
-our $VERSION = '0.06';
+our $VERSION = '0.08';
use 5.006;
-use Sub::Exporter;
use Carp 'confess';
-use Scalar::Util 'blessed';
-use Class::Method::Modifiers ();
+use Mouse::Util 'blessed';
use Mouse::Meta::Attribute;
use Mouse::Meta::Class;
use Mouse::Object;
use Mouse::TypeRegistry;
-do {
- my $CALLER;
-
- my %exports = (
- meta => sub {
- my $meta = Mouse::Meta::Class->initialize($CALLER);
- return sub { $meta };
- },
-
- extends => sub {
- my $caller = $CALLER;
- return sub {
- $caller->meta->superclasses(@_);
- };
- },
-
- has => sub {
- my $caller = $CALLER;
-
- return sub {
- my $meta = $caller->meta;
-
- my $names = shift;
- $names = [$names] if !ref($names);
-
- for my $name (@$names) {
- if ($name =~ s/^\+//) {
- Mouse::Meta::Attribute->clone_parent($meta, $name, @_);
- }
- else {
- Mouse::Meta::Attribute->create($meta, $name, @_);
- }
- }
- };
- },
-
- confess => sub {
- return \&confess;
- },
-
- blessed => sub {
- return \&blessed;
- },
-
- before => sub {
- return \&Class::Method::Modifiers::before;
- },
-
- after => sub {
- return \&Class::Method::Modifiers::after;
- },
-
- around => sub {
- return \&Class::Method::Modifiers::around;
- },
-
- with => sub {
- my $caller = $CALLER;
-
- return sub {
- my $role = shift;
- my $class = $caller->meta;
-
- confess "Mouse::Role only supports 'with' on individual roles at a time" if @_;
-
- Mouse::load_class($role);
- $role->meta->apply($class);
- };
- },
- );
-
- my $exporter = Sub::Exporter::build_exporter({
- exports => \%exports,
- groups => { default => [':all'] },
- });
-
- sub import {
- $CALLER = caller;
-
- strict->import;
- warnings->import;
-
- my $meta = Mouse::Meta::Class->initialize($CALLER);
- $meta->superclasses('Mouse::Object')
- unless $meta->superclasses;
-
- goto $exporter;
- }
+our @EXPORT = qw(extends has before after around blessed confess with);
+
+sub extends { Mouse::Meta::Class->initialize(caller)->superclasses(@_) }
+
+sub has {
+ my $meta = Mouse::Meta::Class->initialize(caller);
- sub unimport {
- my $caller = caller;
+ my $names = shift;
+ $names = [$names] if !ref($names);
- no strict 'refs';
- for my $keyword (keys %exports) {
- next if $keyword eq 'meta'; # we don't delete this one
- delete ${ $caller . '::' }{$keyword};
+ for my $name (@$names) {
+ if ($name =~ s/^\+//) {
+ Mouse::Meta::Attribute->clone_parent($meta, $name, @_);
}
+ else {
+ Mouse::Meta::Attribute->create($meta, $name, @_);
+ }
+ }
+}
+
+sub before {
+ my $meta = Mouse::Meta::Class->initialize(caller);
+
+ my $code = pop;
+
+ for (@_) {
+ $meta->add_before_method_modifier($_ => $code);
}
-};
+}
+
+sub after {
+ my $meta = Mouse::Meta::Class->initialize(caller);
+
+ my $code = pop;
+
+ for (@_) {
+ $meta->add_after_method_modifier($_ => $code);
+ }
+}
+
+sub around {
+ my $meta = Mouse::Meta::Class->initialize(caller);
+
+ my $code = pop;
+
+ for (@_) {
+ $meta->add_around_method_modifier($_ => $code);
+ }
+}
+
+sub with {
+ my $meta = Mouse::Meta::Class->initialize(caller);
+
+ my $role = shift;
+
+ confess "Mouse::Role only supports 'with' on individual roles at a time" if @_;
+
+ Mouse::load_class($role);
+ $role->meta->apply($meta);
+}
+
+sub import {
+ strict->import;
+ warnings->import;
+
+ my $caller = caller;
+
+ my $meta = Mouse::Meta::Class->initialize($caller);
+ $meta->superclasses('Mouse::Object')
+ unless $meta->superclasses;
+
+ no strict 'refs';
+ no warnings 'redefine';
+ *{$caller.'::meta'} = sub { $meta };
+
+ Mouse->export_to_level(1, @_);
+}
+
+sub unimport {
+ my $caller = caller;
+
+ no strict 'refs';
+ for my $keyword (@EXPORT) {
+ delete ${ $caller . '::' }{$keyword};
+ }
+}
sub load_class {
my $class = shift;
functionality, faster. In particular, L<Moose/has> is missing only a few
expert-level features.
+We're also going as light on dependencies as possible. Most functions we use
+from L<Scalar::Util> are copied into this dist. L<Scalar::Util> is required if
+you'd like weak references; there's simply no way to do it from pure Perl.
+L<Class::Method::Modifiers> is required if you want support for L</before>,
+L</after>, and L</around>.
+
=head2 MOOSE COMPAT
Compatibility with Moose has been the utmost concern. Fewer than 1% of the
tests fail when run against Moose instead of Mouse. Mouse code coverage is also
-over 97%. Even the error messages are taken from Moose. The Mouse code just
-runs the test suite 3x-4x faster.
+over 96%. Even the error messages are taken from Moose. The Mouse code just
+runs the test suite 4x faster.
The idea is that, if you need the extra power, you should be able to run
C<s/Mouse/Moose/g> on your codebase and have nothing break. To that end,
Shawn M Moore, C<< <sartak at gmail.com> >>
+Yuval Kogman, C<< <nothingmuch at woobling.org> >>
+
with plenty of code borrowed from L<Class::MOP> and L<Moose>
=head1 BUGS