Eve

 view release on metacpan or  search on metacpan

lib/Eve/Support.pm  view on Meta::CPAN

package Eve::Support;

use strict;
use warnings;

use Contextual::Return;
use PadWalker ();
use Tie::IxHash;

use Eve::Exception;

=head1 NAME

B<Eve::Support> - an utility class that houses various helper functions

=head1 SYNOPSIS

    use Eve::Support;

    Eve::Support::arguments(\%arg_hash,
        my $required_argument, my $optional_argument = 'default value'
    );

=head1 SUBROUTINES

=head2 B<arguments()>

The C<arguments()> method makes it easier to specify a list of required
and optional arguments in any other method. It can be used in both
class method calls and usual subroutine calls.

Here is an example in a usual subroutine:

    sub usual_subroutine {
        my (%arg_hash) = @_;
        Eve::Support::arguments(\%arg_hash,
            my ($required_argument, $another_required_argument),
            my ($optional_argument, $optional_empty_argument) = (1, \undef)
        );
    }

The same may be done in a class method call:

    sub class_method {
        my ($self, %arg_hash) = @_;
        Eve::Support::arguments(\%arg_hash,
            my ($required_argument, $another_required_argument),
            my ($optional_argument, $optional_empty_argument)
                = ('default', \undef)
        );
    }

If the function is called in the RVALUE context it skips the
redundancy check and returns the rest of arguments that have not been
processed as a hash reference.

    sub foo {
        my (%arg_hash) = @_;
        my $rest_hash = Eve::Support::arguments(
            \%arg_hash, my $bar);

        return $rest_hash;
    }

Here the call C<foo(bar => 1, baz => 2, bad => 3)> will return the
hash C<{'baz' => 2, 'bad' => 3}>.

=head3 Arguments

=over 4

=item C<\%arg_hash>

A reference to a hash of arguments that has been passed into the
current method.

=item C<@variable_list>

A list of variables that have to be filled by values from the
incoming C<\%arg_hash>.

=back

=head3 Throws

=over 4

=item C<Eve::Error::Attribute>

could not get a variable for a named argument, an argument is required
or an argument is redundant.

=back

=cut

sub arguments : lvalue {
    my $arg_hash = shift;

    foreach my $var (@_) {
        my $name = PadWalker::var_name(1, \$var);
        if (not defined($name)) {
            Eve::Error::Attribute->throw(
                message => 'Could not get a variable for a named argument');
        }

        $name =~ s/^\$//;

        if (exists($arg_hash->{$name})) {
            $var = $arg_hash->{$name};
            delete($arg_hash->{$name});
        } else {
            if (defined($var)) {
                if ($var eq \undef) {
                    # Work around default undef value
                    $var = undef;
                } else {
                    # Leave the value that was assigned
                }
            } else {
                Eve::Error::Attribute->throw(
                    message => 'Required argument: '.$name);
            }
        }
    }

    NVALUE {
        my @keys = keys(%$arg_hash);
        if (@keys) {
            Eve::Error::Attribute->throw(
                message => 'Redundant argument(s): '.join(', ', sort(@keys)));
        }
    }
    RVALUE {
        $arg_hash;
    }
}

=head2 B<unique()>

=head3 Arguments

=over 4

=item C<list>

=back

=head3 Returns

A list containing only unique elements of the passed list.

=cut

sub unique {
    my %arg_hash = @_;
    Eve::Support::arguments(\%arg_hash, my $list);

    my $unique_list = [];
    my $seen_hash = {};
    for my $item (@{$list}) {



( run in 1.854 second using v1.01-cache-2.11-cpan-39bf76dae61 )