=pod

=head1 NAME

Mite::Manual::Keywords - functions exported by Mite

=head1 MANUAL

To start a class:

    use Your::Project::Mite;

If you need to provide additional options:

    use Your::Project::Mite qw( some options );

To start a role:

    use Your::Project::Mite -role;

Or with additional options:

    use Your::Project::Mite qw( -role some options );

Options which look like words are requesting the import of a keyword of
that name. For example, this imports a keyword called C<lazy>:

    use Your::Project::Mite qw( lazy );

Options which start with an exclamation mark are the negation of that.
For example to unrequest C<lazy>:

    use Your::Project::Mite qw( !lazy );

Options starting with a hyphen are either a bundle of keywords, or
are a pragma which affect your class as a whole.

By default, classes get the C<has>, C<extends>, C<with>, C<before>, C<after>,
C<around>, and C<signature_for> keywords imported into them.

By default, roles get C<has>, C<requires>, C<with>, C<before>, C<after>,
C<around>, and C<signature_for> keywords imported into them.

The C<< !-defaults >> flag suppresses the defaults from being imported.

The C<< -all >> flag imports everything possible.

=head2 C<< has $name => %spec >>

Like C<has> in Moose, this declares one or more attributes. See
L<Mite::Manual::Attributes> for further details.

Mite supports the shortcut found in L<Mojo::Base> and L<Object::Simple>:

    has $name => $default;

In these cases, if C<$default> is a coderef, the attribute will use it as
a I<builder> and assume the attribute C<< is => 'lazy' >>, and otherwise
will treat C<$default> as a I<default> and assume the attribute
C<< is => 'ro' >>.

If additional options are needed they can be provided, but by that point
it's probably better to abandon the shortcut syntax.

    has myattr => sub {
        return {};
    }, is => 'rwp', isa => 'HashRef';

=head2 C<< extends @parents >>

Declares the parent classes for your class.

You cannot use C<extends> from within roles.

Like Moose, you can require a minimum version of a parent class:

    extends(
        'Your::Project::SomeClass  => { -version => '1.000' },
        'Your::Project::OtherClass => { -version => '2.000' },
    );

Multiple inheritance is supported if you're inheriting from Mite classes
within your project. Single inheritance is supported if you're inheriting
from a "foreign" class, as long as it uses a blessed hashref. (Multiple
inheritance may in some cases work.)

=head2 C<< requires @methods >>

Works as in L<Moose>.

You cannot use C<requires> from within classes.

=head2 C<< with @roles >>

Works as in L<Moose>.

Roles must be Mite roles created in your own project, or Role::Tiny roles.
Mite does not support using roles from other projects, or using role
implementations other than Mite and Role::Tiny.

Like Moose, you can require a minimum version of a role:

    with(
        'Your::Project::SomeRole  => { -version => '1.000' },
        'Your::Project::OtherRole => { -version => '2.000' },
    );

You can also alias and exclude methods (but not attributes) provided by
roles:

    with 'Your::Project::Mouth' => {
        -excludes => [ 'speak' ],
        -alias    => { 'belch' => 'burp' },
    };

=head2 C<param> and C<field>

The C<param> and C<field> keywords are available, like L<MooseX::Extended>.
These act as an alternative to C<has>.

    use Your::Project::Mite qw( param field !has );
    
    param foo => ( isa => 'Str' );

=head2 C<before>, C<around>, and C<after>

Basic versions of the C<before>, C<around>, and C<after> method modifiers
are provided, but these may run in a different order from Moose if you
use several modifiers on the same method.

=head2 C<< signature_for $method_name => %spec >>

Installs a wrapper for a method enforcing a method signature, inspired by
L<Type::Params>. This is installed via the same mechanism as C<around>,
so is sensitive to the same concerns with regard to ordering, etc.

Simple example of named parameters:

    signature_for my_method => (
        named => [
            foo  => 'Bool',
            bar  => 'Int', { default => 42 },
        ],
    );
    
    sub my_method {
        my ( $self, $arg ) = @_;
        
        if ( $arg->foo ) {
            return $arg->bar / 2;
        }
        else {
            return $arg->bar * 2;
        }
    }
    
    $object->my_method( foo => true, bar => 30 );
    $object->my_method( { foo => true, bar => 36 } );
    $object->my_method( foo => false );

Simple example using positional parameters:

    signature_for my_method => (
        pos => [
            'Bool',
            'Int', { default => 42 },
        ],
    );
    
    sub my_method {
        my ( $self, $foo, $bar ) = @_;
        
        if ( $foo ) {
            return $bar / 2;
        }
        else {
            return $bar * 2;
        }
    }
    
    $object->my_method( true, 30 );
    $object->my_method( false );

Simple example using named-to-list (named on the outside, positional on the
inside):

    signature_for my_method => (
        named => [
            foo => 'Bool',
            bar => 'Int', { default => 42 },
        ],
        named_to_list => true,
    );
    
    sub my_method {
        my ( $self, $foo, $bar ) = @_;
        
        if ( $foo ) {
            return $bar / 2;
        }
        else {
            return $bar * 2;
        }
    }
    
    $object->my_method( foo => true, bar => 30 );
    $object->my_method( { foo => true, bar => 36 } );
    $object->my_method( foo => false );

You can indicate that your sub is designed to be called as a function instead
of a method (no C<< $self >>):

    signature_for my_func => (
        ...,
        method => false,
    );

If you override a method with a signature in a parent class, then the
parent's signature won't wrap the child's method, but you can inherit
its signature:

    signature_for '+my_func';

This will wrap your overridden method in the same signature as the parent
method.

You can also modify the parent class signature in your child class to add
extra named or positional parameters:

    signature_for '+my_func' => (
        pos => [ Int ],
    );

You cannot add parameters like this if the parent class's signature has a
slurpy parameter. Nor can you add positional parameters if the parent class's
signature has named parameters or vice versa. If you need to radically change
the parent class's signature, it's best not to use the C<< + >> sign, and
instead define a whole new signature for the child class.

A role can define a signature and this signature will be applied to classes
that consume the role:

    package Your::Project::MessageTarget;
    use Your::Project::Mite -role, -all;
    
    signature_for send_message => (
        named => [
            subject => Str,
            body    => Str,
        ],
    );
    
    package Your::Project::Console;
    use Your::Project::Mite -all;
    with 'Your::Project::MessageTarget';
    
    has handle => sub { \*STDOUT };
    
    sub send_message {
        my ( $self, $arg ) = @_;
        print { $self->handle } $arg->subject, "\n";
        print { $self->handle } $arg->body, "\n\n";
        return;
    }

Using C<< + >> to extend signatures from roles is not currently supported.

=head2 C<true> and C<false>

Although they're not imported by default, you can import C<true> and
C<false> keywords. They can made attribute definitions a little prettier:

    use Your::Project::Mite qw( true false );
    # OR:
    use Your::Project::Mite qw( -bool );
    
    has foo => (
        is => 'rw',
        required => true,
    );

=head2 C<ro>, C<rw>, C<rwp>, C<bare>, and C<lazy>.

You can export constants called C<ro>, C<rw>, C<rwp>, C<bare>, and C<lazy>.
Again, these can make attribute definitions prettier:

    use Your::Project::Mite qw( ro rw -bool );
    # OR:
    use Your::Project::Mite qw( -is -bool );
    
    has foo => ( is => rw, required => true );

Even though C<< is => 'locked' >> is allowed, there's no C<locked> export.

=head2 C<carp>, C<croak>, and C<confess>

These functions can be exported to your class:

    use Your::Project::Mite qw( croak );
    
    sub my_method {
        croak 'Not implemented yet';
    }

The functions provided are superpowered versions of the ones from L<Carp>.
If called with multiple arguments, the first is treated as a format string
for C<sprintf> and the remainder are passed through L<Data::Dumper> if they
are references.

    sub my_method {
        my $self = shift;
        croak '%s does not implement this method', ref( $self );
    }

=head2 C<blessed>

C<blessed> from L<Scalar::Util> can also be imported.

    use Your::Project::Mite qw( blessed );

=head2 C<STRICT>

A function similar to C<STRICT> from L<Devel::StrictMode> can be imported.

This allows you to do things like:

    sub my_method {
        my $self = shift;
        croak "Should be called as an object method!"
            if STRICT && ! blessed( $self );
        
        ...;
    }

The C<STRICT> constant will be true if running under author testing, but
usually false when running on end user's machines. This allows you to catch
errors on your own machine but avoid slow error checking on the end user's
machine.

=head2 C<guard>

A function similar to C<guard> from L<Scope::Guard> can be imported.

    use Your::Project::Mite qw( guard );
    
    # Says "Hello world"
    do {
        my $guard = guard { print "world\n" };
        print "Hello ";
    };

=head C<lock> and C<unlock>

These can be used to lock and unlock locked attributes.

    use Your::Project::Mite qw( lock unlock true false );
    
    has numbers => (
        is      => 'ro',
        default => [],
        locked  => true,
    );
    
    ...
    
    sub push_number {
        my ( $self, $number ) = @_;
        my $guard = unlock( $self->numbers );
        push @{ $self->numbers }, $number;
        return $self;
    }

C<< lock($ref) >> will make an arrayref or hashref read-only.

C<< unlock($ref) >> will make a locked arrayref or hashref read-write, and
return a guard object. When the guard object goes out of scope, the reference
will automatically lock itself again!

=head1 BUGS

Please report any bugs to L<https://github.com/tobyink/p5-mite/issues>.

=head1 AUTHOR

Michael G Schwern E<lt>mschwern@cpan.orgE<gt>.

Toby Inkster E<lt>tobyink@cpan.orgE<gt>.

=head1 COPYRIGHT AND LICENCE

This software is copyright (c) 2011-2014 by Michael G Schwern.

This software is copyright (c) 2022 by Toby Inkster.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=head1 DISCLAIMER OF WARRANTIES

THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

=cut
