=pod

=head1 NAME

Mite::Manual::Attributes - options for defining attributes with Mite

=head1 SYNOPSIS

    has myattr => (
        alias         => [ 'my_attr' ],
        is            => 'bare',       # or ro/rw/rwp/lazy
        init_arg      => 'myattr',
        required      => true,
        reader        => 'get_myattr',
        writer        => 'set_myattr',
        accessor      => 'access_myattr',
        clearer       => 'clear_myattr',
        predicate     => 'has_myattr',
        lvalue        => 'myattr',
        local_writer  => 'locally_set_myattr',
        # default     => sub { shift->_build_myattr },
        builder       => '_build_myattr',
        lazy          => false,
        isa           => 'Object',
        coerce        => false,
        clone         => false,
        locked        => false,
        handles       => { quux => 'quuux' },
        handles_via   => [ 'Blessed' ],
        trigger       => '_trigger_myattr',
    );

Shortcut for a lazy builder:

    has myattr => sub { ... };

Shortcut for a simple default:

    has myattr => "some value";

=head1 MANUAL

Like C<has> in Moose, this declares an attribute.

Multiple attributes can be defined using an arrayref.

    # Defines get_foo, get_bar, set_foo, and set_bar.
    #
    has [ 'foo', 'bar' ] => (
        isa => 'Str',
        reader => 1,
        writer => 1,
    );

=head2 Extending attributes

Like in Moose, you can use a plus sign to modify an attribute definition
from a role or parent class:

    has '+foo' => (
        default => sub { 'new default' },
    );

When modifying an attribute, you cannot use the C<is> option.

=head2 Attribute storage

Mite objects are always blessed hashrefs, and the name of the attribute
is the hash key used to store the attribute.

It is the maintainer of Mite's opinion that it is acceptable for an object
method to directly access its own attributes this way, but not attributes
defined in roles, parent classes, etc. Bypassing accessors will cause type
checks, lazy defaults, triggers, etc to be ignored, so should be done with
caution.

=head2 Attribute options

The following options are supported. (Expected types for the value of
each option are also provided. A B<MethodName> is any valid Perl sub
name; a B<MethodNameTemplate> may also contain "%s" as a placeholder;
B<One> means the literal string "1". Other type constraints are
self-explanatory.)

=head3 C<is> B<< Enum[ "ro", "rw", "bare", "rwp", "lazy", "locked" ] >>

These are all just shortcuts for defining other options.

Supported values for C<is> include "ro", "rw", and "bare" like Moose,
but also "rwp" and "lazy" like Moo. Lastly "locked" is an alias for "ro",
but also sets the C<locked> option to true.

The default is C<< is => 'bare' >>.

=head3 C<reader> B<< MethodNameTemplate | One | Undef >>

The name of the attribute reader method to generate. If set to "1",
will generate a reader called "get_foo" if your attribute is called
"foo" and "_get__foo" if your attribute is called "_foo".

If your attribute is defined as C<< is => "ro" >>, C<< is => "rwp" >>,
C<< is => "lazy" >>, or C<< is => "locked" >>, then C<reader> defaults to
C<< $name >>.

If your reader contains "%s" this will be replaced by the name of the
attribute. This allows:

    # readers called "fetch_foo" and "fetch_bar"
    has [ 'foo', 'bar' ] => (
        required => true,
        reader   => 'fetch_%s',
    );

=head3 C<writer> B<< MethodNameTemplate | One | Undef >>

The name of the attribute writer method to generate. If set to "1",
will generate a writer called "set_foo" if your attribute is called
"foo" and "_set__foo" if your attribute is called "_foo". 

If your attribute is defined as C<< is => "rwp" >>, then C<writer>
defaults to C<< "_set_$name" >>.

If your writer contains "%s" this will be replaced by the name of the
attribute.

Mite provides a similar feature to L<MooseX::Attribute::Chained>, so
writer methods return C<< $self >>, allowing them to be chained:

    $object->set_bar( 42 )->set_baz( 99 );

=head3 C<accessor> B<< MethodNameTemplate | One | Undef >>

The name of the dual-purpose attribute reader/writer method to generate.
If set to "1", will generate a reader called "foo" if your attribute is
called "foo" and "_foo" if your attribute is called "_foo". 

If your attribute is defined as C<< is => "rw" >>, then C<accessor>
defaults to C<< $name >>.

If your accessor contains "%s" this will be replaced by the name of the
attribute.

Mite provides a similar feature to L<MooseX::Attribute::Chained>, so
accessor methods called as writers return C<< $self >>, allowing them
to be chained:

    $object->bar( 42 )->baz( 99 );

=head3 C<clearer> B<< MethodNameTemplate | One | Undef >>

The name of the attribute clearer method to generate. If set to "1",
will generate a clearer called "clear_foo" if your attribute is called
"foo" and "_clear__foo" if your attribute is called "_foo".

If your clearer contains "%s" this will be replaced by the name of the
attribute.

Mite provides a similar feature to L<MooseX::Attribute::Chained>, so
clearer methods return C<< $self >>, allowing them to be chained:

    $object->clear_foo->clear_bar->clear_baz;

=head3 C<predicate> B<< MethodNameTemplate | One | Undef >>

The name of the attribute predicate method to generate. If set to "1",
will generate a predicate called "has_foo" if your attribute is called
"foo" and "_has__foo" if your attribute is called "_foo".

If your predicate contains "%s" this will be replaced by the name of the
attribute.

=head3 C<lvalue> B<< MethodNameTemplate | One | Undef >>

The name of the dual-purpose lvalue reader/writer method to generate.
If set to "1", will generate a reader called "foo" if your attribute is
called "foo" and "_foo" if your attribute is called "_foo".

If your accessor contains "%s" this will be replaced by the name of the
attribute.

lvalue accessors are used like this:

    my $object = MyClass->new( myattr => 99 );
    say $object->myattr;   # ==> 99
    $object->myattr = 66;  # set new value
    say $object->myattr;   # ==> 66

An attribute cannot have an lvalue accessor if it has a lazy builder/default,
uses a type contraint or coercions, has a trigger, or uses weak_ref.

This is roughly (but not exactly) the same functionality as
L<MooseX::LvalueAttribute>.

=head3 C<local_writer> B<< MethodNameTemplate | One | Undef >>

The name of the dynamically scoped writer method to generate. These work like
this:

    my $object = Your::Project::SomeClass->new( foo => 99 );
    say $object->foo;      # ==> 99
    do {
        my $guard = $object->locally_set_foo( 66 );
        say $object->foo;  # ==> 66
    };
    say $object->foo;      # ==> 99

When the C<< $guard >> goes out of scope, the old value will be restored.
The C<< $guard >> object also has three methods: C<restore> to restore the
old value immediately, C<dismiss> to dismiss the old value and keep the
new value, and C<peek> to peek at the old value.

If the local writer is called with no parameter, it acts as a local clearer.

If set to "1", will generate a local writer called "locally_set_foo" if your
attribute is called "foo" and "_locally_set__foo" if your attribute is
called "_foo". 

If your local writer contains "%s" this will be replaced by the name of the
attribute.

This is vaguely inspired by L<MooseX::LocalAttribute>.

=head3 C<skip_argc_check> B<Bool>

Mite includes sanity checks on the number of arguments passed to accessors.
For example, if you call a reader and pass it a value as if it were a writer,
it will die with a message explaining the problem.

You can set C<skip_argc_check> to true to skip these checks for an attribute's
accessors, making it run a little faster. If Class::XSAccessor is installed and
being used, these checks will still be done in XS mode, so C<skip_argc_check>
shouldn't be used as a way to allow the wrong number of arguments to be passed
to a function, just as an optimization.

=head3 C<handles> B<< Map[ MethodNameTemplate, MethodName ] | Int >>

Delegated methods. Currying and native traits are not supported.

If your handles hashref keys contain "%s", they will be replaced by
the name of the attribute.

    # $this->user_agent_get is a shortcut for $this->user_agent->get
    #
    has user_agent => (
        required => true,
        isa      => 'Object',
        handles  => {
            '%s_get'  => 'get',
            '%s_post' => 'post',
        },
    );

If the attribute's type constraint is an enumeration, then the shortcuts
C<< handles => 1 >> and C<< handles => 2 >> are also supported. These
are inspired by L<MooseX::Enumeration> and L<MooX::Enumeration>.

In this example, Mite creates methods C<< is_alive >> and C<< is_dead >>
for you:

    has status => (
        enum     => [ 'alive', 'dead' ],
        handles  => 1,
        default  => 'alive',
        writer   => '_set_status',
    );
    
    sub kill {
        my $self = shift;
        croak "Already dead!" if $self->is_dead;
        $self->_set_status( 'dead' );
    }

In this example, Mite creates C<< size_is_small >>, C<< size_is_medium >>,
and C<< size_is_large >> for you.

    has size => (
        is       => 'rw',
        isa      => 'Enum[ "small", "medium", "large" ]',
        handles  => 2,
    );

Note that if C<handles> had been 1, then the methods would have just been
called C<is_small>, C<is_medium>, and C<is_large>, without the C<size_> prefix
at the start.

=head3 C<handles_via> B<< ArrayRef[Str] | Str >>

If C<handles_via> is set, then Mite will use L<Sub::HandlesVia> for dealing
with the C<handles> option instead of trying to deal with it internally. This
allows a rich set of delegations to native Perl types like arrayrefs and
hashrefs.

    has monkeys => (
        is          => 'bare',
        isa         => 'ArrayRef[Object]',
        handles_via => 'Array',
        handles     => {
            '%s'          => 'all',
            monkey_count  => 'count',
            add_monkey    => 'push...',
            find_monkeys  => 'grep',
            clear_monkeys => 'clear...',
        },
    );
    
    ...
    
    $zoo->clear_monkeys();
    $zoo->add_monkey( $bobo );
    $zoo->add_monkey( $momo );
    if ( $zoo->monkey_count == 0 ) {
        say "No monkeys!";
    }
    for my $monkey ( $zoo->monkeys ) {
        say $monkey->name;
    }

Most L<Sub::HandlesVia> features should be supported.

=head3 C<init_arg> B<< NonEmptyStr | Undef >>

The parameter expected to be passed to the constructor to initialize this
attribute. May be undef if the attribute should not be intitialized in the
constructor.

Defaults to the attribute's name.

If your init_arg contains "%s" this will be replaced by the name of the
attribute.

=head3 C<required> B<Bool>

Indicates whether the attribute is required in the constructor. If the
attribute has a non-lazy default, this is ignored.

=head3 C<alias> B<< ArrayRef[ MethodNameTemplate ] >>

A list of aliases for the attibutes. If the attribute has an init_arg
(including a default one), this provides alternative initialization
arguments. If the attribute C<< is => "rw" >>, then these aliases are
aliases for the accessor; otherwise they are aliases for the reader.

The strings can contain "%s" which will be replaced by the attribute
name, allowing this to work:

    has [ 'foo', 'bar' ] => (
        is => 'ro',
        alias => [ 'get_%s' ],
    );

If you try to create aliases but don't have a reader or accessor,
then as a last resort the alias will be an alias for the writer.

    # foo can be set using `set_foo` or `whatever`
    #
    has foo => (
        is => 'bare',
        writer => 1,
        alias => 'whatever',  # Mite will implicitly do Str -> ArrayRef here
    );

Aliases are not natively supported by Moose, but this feature is
analagous to L<MooseX::Aliases>.

=head3 C<isa> B<< Str | Ref >>

A string type name from L<Types::Standard>, L<Types::Common::String>,
or L<Types::Common::Numeric>, or a blessed L<Type::Tiny> object.
Alternatively, any reference which C<to_TypeTiny> from L<Types::TypeTiny>
is able to coerce to a blessed Type::Tiny object, or any blessed object
that provides a C<to_TypeTiny> method which returns a Type::Tiny object.
If using a blessed object, you'll be introducing a dependency for your
project on whatever type constraint library you're using, so prefer
string type contraint names.

Any string supported by L<Type::Utils> C<dwim_type> is supported, so
things like C<< "Int | Enum['small', 'medium', 'large']" >> should work!

If you need custom types, you can add something like this to your
F<.mite/config>:

    types: Your::Project::Types

The module C<Your::Project::Types> would be a type library constructed with
L<Type::Library>. It should just contain type constraints and coercions which
can be inlined, and none of your classes should load it directly (just rely
on Mite to load it). This way you can use custom types in your project and
your project will not have a dependency on Type::Library.

L<Type::Library::Compiler> is an alternative way to create a zero-dependency
type library which Mite is able to use.

=head3 C<does> B<< Str | Ref >>

Same as C<isa>, but if the type name is unrecognized, assumes it was a
role name instead of assuming it was a class name.

=head3 C<enum> B<< ArrayRef[ NonEmptyStr ] >>

Shortcut for C<< isa => 'Enum["foo","bar","baz"]' >>.

This feature is inspired by L<MooseX::Enumeration> and L<MooX::Enumeration>.

=head3 C<coerce> B<Bool>

Indicates that the attribute should attempt to coerce values to fit
the type constraint.

=head3 C<trigger> B<< MethodNameTemplate | One | CodeRef >>

If set to a string, is the name of a method to call whenever a new
attribute value is set. This is I<not> called when an attribute is
defaulted. (However, see the C<default_does_trigger> option.) If set
to "1", will assume a trigger called "_trigger_foo" if your attribute
is called "foo" and "_trigger__foo" if your attribute is called "_foo".

If set to a coderef, acts like it was set to "1" but installs the
coderef into your class with that name.

If your trigger method name contains "%s" this will be replaced by
the name of the attribute.

=head3 C<weak_ref> B<Bool>

Indicates that the attribute should weaken its reference to the
attribute value.

=head3 C<locked> B<Bool>

If an attribute is locked and its value is set to an unblessed arrayref or
hashref, then the array or hash will be marked as read-only. This means that
if you've defined an attribute like this:

    has numbers => (
        is          => ro,
        isa         => 'ArrayRef',
        locked      => true,
        default     => [],
    );

People will not be able to do C<< push( @{ $object->numbers }, 1 ) >>, and it
will throw an exception!

To allow people to push to the array:

    has numbers => (
        is          => ro,
        isa         => 'ArrayRef',
        locked      => true,
        default     => [],
        handles_via => 'Array',
        handles     => { add_number => 'push', remove_number => 'pop' },
    );

Then they can use C<< $object->add_number( 1 ) >>.

Defaults to false, unless C<< is => "locked" >>.

=head3 C<clone> B<< MethodNameTemplate | One | CodeRef | Undef >>

Stolen from L<MooseX::Extended>. Set to "1" to make a deep clone of
the attribute value using L<Storable> whenever the attribute is read
or written. If set to a method name or coderef, then the method will be
called as C<< $self->$method( $attrname, $value ) >> and is expected
to return a clone of the value.

    has start_date => (
        is       => ro,
        isa      => 'InstanceOf["DateTime"]',
        required => true,
        clone    => sub {
            my ( $self, $attrname, $value ) = @_;
            return $value->clone;
        },
    );

This option can be fine-tuned by setting the C<clone_on_read> and
C<clone_on_write> boolean options. By default, attributes which have
a clone method set will clone both incoming and outgoing references.

    has start_date => (
        is       => ro,
        isa      => 'InstanceOf["DateTime"]',
        required => true,
        clone    => sub {
            my ( $self, $attrname, $value ) = @_;
            return $value->clone;
        },
        clone_on_write => true,
        clone_on_read  => false,
    );

=head3 C<default> B<< CodeRef | ScalarRef | Str | Undef | Dict[] | Tuple[] >>

A default value for the attribute, or a coderef called as a method
to generate that default value.

Unlike Moose, you can alternatively include an inline string of Perl
code as a ScalarRef:

    has list => (
        is => 'ro',
        isa => 'ArrayRef',
        default => \ '[]',
    );

This has performance benefits over using a coderef as it avoids the
overhead of a sub call.

An I<empty> arrayref or I<empty> hashref is also allowed as a default.

=head3 C<builder> B<< MethodNameTemplate | One | CodeRef >>

If set to a string, is the name of a method to call to build the
default attribute value. If set to "1", will assume a builder called
"_build_foo" if your attribute is called "foo" and "_build__foo" if your
attribute is called "_foo".

If you used C<< is => "lazy" >>, this will default to "1".

If set to a coderef, acts like it was set to "1" but installs the
coderef into your class with that name.

If your builder method name contains "%s" this will be replaced by
the name of the attribute.

=head3 C<lazy> B<Bool>

Indicates that the default should be set lazily. Defaults to false
unless you used C<< is => "lazy" >>.

An eager (non-lazy) default or builder is applied by the constructor
when the object is constructed. A lazy default or builder is applied
by the reader/accessor if and when the attribute is accessed.

=head3 C<default_is_trusted> B<Bool>

Defaults to false (which is how Moose and Moo work), but if set to true,
Mite will skip type checks and coercions when the attribute is set by the
default or builder. If you trust that the default is always going to be
a valid value, then it may make sense to only do type checks and coercions
when a value is passed in by your caller. This may make your accessors and
constructor a little faster.

=head3 C<default_does_trigger> B<Bool>

Defaults to false (which is how Moose and Moo work), but if set to true,
Mite will also call your trigger if the attribute's default is used.
Normally triggers are only called when an attribute is set explicitly.

=head3 C<documentation> B<Any>

This option is ignored, but you can set it to a documentation string
for your attribute.

    has name => (
        is => 'rwp',
        isa => 'Str',
        documentation => 'First name and surname',
    );

=head2 How to...

=head3 C<< is => 'wo' >> (write-only attributes)

There are use cases for write-only attributes. For example:

    package Your::Project::ApiClient;
    use Your::Project::Mite;
    has user_agent => (
        is      => 'wo',
        isa     => 'Object',
        handles => [ 'get', 'post' ],
        builder => sub { require HTTP::Tiny; HTTP::Tiny->new },
    );
    ...
    
    $client->user_agent( HTTP::Tiny::WithLogging->new );
    $client->post( ... );
    $client->user_agent();  # dies, because it's a writer

However, Mite doesn't support C<< is => 'wo' >>. (Neither do L<Moose>,
L<Mouse>, or L<Moo>!) So how can this be accomplished?

This will provide a writer method called C<user_agent>:

    has user_agent => (
        writer  => '%s',
        isa     => 'Object',
        handles => [ 'get', 'post' ],
        builder => sub { require HTTP::Tiny; HTTP::Tiny->new },
    );

Alternatively, this will provide a writer method called C<set_user_agent>:

    has user_agent => (
        writer  => 1,
        isa     => 'Object',
        handles => [ 'get', 'post' ],
        builder => sub { require HTTP::Tiny; HTTP::Tiny->new },
    );

=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
