NAME
    MooseX::Params - Parameters with meta, laziness and %_

VERSION
    version 0.002

SYNOPSIS
        package MySystem;

        use MooseX::Params;

        method 'login',
            params => [
                username => { required => 1, isa => 'Str' },
                password => { required => 1, isa => 'Str' },
            ],
            sub {
                my $user = $self->load_user($_{username});
                $_{password} eq $user->password ? 1 : 0;
            };

        method 'load_user' ...

DESCRIPTION
    This modules puts forward several proposals to evolve perl's method
    declaration and parameter processing syntax. For the original rationale
    see <http://mechanicalrevolution.com/blog/parameter_apocalypse.html>.

    The proposed interface is based on three cornerstone propositions:

    *   Parameters are first-class entities that deserve their own meta
        protocol. A common meta protocol may be used by different
        implementations (e.g. this library, MooseX::Params::Validate,
        MooseX::Method::Sigantures) and allow them to coexist better. It is
        also the necessary foundation for more advanced features such as
        multimethods and extended role validation.

    *   Parameters should benefit from the same power and flexibility that
        Moose attributes have. This module implements most of this
        functionality, including laziness.

    *   The global variable %_ is used as a placeholder for processed
        parameters. It is considered by the author of this module as an
        intuitive alternative to manual unpacking of @_ while staying within
        the limits of traditional Perl syntax.

DO NOT USE
    This is an experimental module and has been uploaded to CPAN for
    showcase purposes only. It is incomplete, slow, buggy, and does not come
    with any maintenance guarantee. At this point it is not suitable for use
    in production environments.

METHODS
    "MooseX::Params" exports the "method" keyword which is used to declare a
    new method. The simplest method declaration consists of a method name
    and code to execute:

        method do_something => sub { ... };

    You can specify other options when declaring a method, but a trailing
    sub is always considered the method body:

        method do_something => (
            params => ... # declare parameters
            sub { ... }   # body
        );

    The method body can also be explicitly specified via the "execute"
    option:

        method do_something => (
            params  => ...         # declare parameters
            execute => sub { ... } # body
        );

    This syntax allows for a method to have more than one executable parts
    (think "BUILD" and "BUILDARGS" for Moose constructors):

        # pseudo code - 'buildargs' and 'build' are not implemented yet!
        method do_something => (
            params    => ...          # declare parameters
            buildargs => sub { ... }, # coerce a different signature
            build     => sub { ... }, # perform more complex checks
            execute   => sub { ... }, # body
        );

    The "execute" option can also point to the name of a subroutine to use
    as the method body:

        method do_something => (
            params  => ...
            execute => '_execute_do_something'
        );

        sub _execute_do_something { ... }

    Actually if no method body is specified it will default to a sub named
    "_execute_$method_name":

        method 'do_something';

        sub _execute_do_something { ... }

PARAMETERS
  Parameter names
    Each parameter, whether passed in a named or positional fashion, has a
    name. The simplest parameter declaration looks like this:

        method do_something => (
            params => [qw(first second third)],
            sub { ... }
        );

    This declares a method with three positional parameters, called
    respectively "first", "second" and "third". No validation or processing
    options have been specified for these parameters. You can now execute
    this method as:

        $self->do_something($first_argument, $second_argument, $third_argument);

  %_ and $self
    This module takes a somewhat radical approach to accessing method
    parameters. It introduces two global variables in the using module's
    namespace: %_ and $self. Within a method body, $self is always localized
    to the method's invocant. The special %_ hash contains the processed
    values of all parameters passed to the method:

        has separator => ( is => 'ro', isa => 'Str', default => ',' );

        method print_something => (
            params => [qw(first second third)],
            sub { print join $self->separator, @_{qw(first second third)} }
        );

    Note that %_ is a read-only hash: any attempt to assign values to it
    will currently throw an exception. An exception will also be thrown if
    you attempt to access an element whose key is not a valid parameter
    name. @_ is also available if you want to do traditional-style unpacking
    of your parameters.

    The downside of the current implementation is that functions called from
    within your method may access their caller's $self and %_ variables
    (this is not impossible to remedy though).

  Parameter processing
    The main purpose of this module is to bring the full power of Moose
    attributes to parameter processing. From the Moose documentation:

        Moose attributes have many properties, and attributes are probably the single most powerful and flexible part of Moose.
        You can create a powerful class simply by declaring attributes.
        In fact, it's possible to have classes that consist solely of attribute declarations.

    Therefore, the parameter declaration API aims to mirror "Moose"'s
    attribute API as close as possible:

        method 'login' => (
            params => [
                username => { required => 1, isa => 'Str' },
                password => { required => 1, isa => 'Str' },
            ],
            sub {
                my $user = $self->load_user($_{username});
                $_{password} eq $user->password ? 1 : 0;
            }
        );

    The following options are currently supported (most of them should be
    self-explanatory):

    *   required

    *   isa

    *   coerce

    *   default

    *   builder

    *   lazy

    *   lazy_build

    *   documentation

    Other options (e.g. traits, triggers, etc.) will be supported in the
    future.

  Lazy building
    Lazy building requires some explanation. As with Moose attributes, the
    value of a parameter marked as lazy will not be processed until the
    first attempt to access it. This means that you can create parameters
    with expensive builders that will not execute if the code where they are
    called is never reached.

        method 'login' => (
            params => [
                username => { required => 1, isa => 'Str' },
                password => { required => 1, isa => 'Str' },
                user     => { lazy => 1, builder => '_build_param_user' },
            ],
            sub {
                return unless $self->login_enabled;
                $_{password} eq $_{user}->password ? 1 : 0;
            }
        );

        sub _build_param_user { $self->load_user($_{username}) }

    Within a parameter builder you can access $self and %_ just as in the
    method body. %_ contains all parameters processed so far and is still
    read-only. The builder must return the value of the requested parameter.

    The "lazy_build" option is a shortcut for:

        required => 1, lazy => 1, builder => "_build_param_$param_name"

  Named vs. positional
    By default all parameters are positional. You can ask for named
    parameters via the "type" option:

        method 'login' => (
            params => [
                username => { required => 1, isa => 'Str', type => 'named' },
                password => { required => 1, isa => 'Str', type => 'named' },
            ],
            sub { ...  }
        );

        $self->login( username => $username, password => $password );

    You can also mix named and positional parameters, as long as all
    positional parameters come first and are required:

        method 'login' => (
            params => [
                username => { required => 1, isa => 'Str', type => 'positional' },
                password => { required => 1, isa => 'Str', type => 'positional' },
                remember => { isa => 'Bool', type => 'named' },
                secure   => { isa => 'Bool', type => 'named' },
            ],
            sub { ...  }
        );

        $self->login( $username, $password, remember => 1, secure => 0 );

    More complex parameter passing styles are expected to be supported in
    the future (e.g. named parameters in a hashref).

META CLASSES
    "MooseX::Params" provides class, method and parameter metaroles, please
    see their sourcecode for detail (plain Moose):

    *   MooseX::Params::Meta::Class

    *   MooseX::Params::Meta::Method

    *   MooseX::Params::Meta::Parameter

TODO
    This module is still in its infancy. Some of the more important planned
    features include:

    *   declaration of class-level parameters reusable across multiple
        methods

    *   return value validation

    *   multimethods

    *   "BUILDARGS" and "BUILD" for methods

    *   a "function" keyword with similar syntax

    Whether or not these features will be implemented depends mostly on the
    community response to the proposed API. Currently the best way to
    contribute to this module would be to provide feedback and commentary -
    the Moose mailing list will be a good place for this.

SEE ALSO
    *   MooseX::Params::Validate

    *   MooseX::Method::Signatures

AUTHOR
    Peter Shangov <pshangov@yahoo.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2011 by Peter Shangov.

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

