=encoding utf8

=head1 NAME

Module::Generic::Array - An Array Manipulation Object Class

=head1 SYNOPSIS

    my $ar = Module::Generic::Array->new( [qw( Joe John Mary )] );
    printf( "There are %d people\n", $ar->length );
    # Adding one more
    $ar->push( "Jack" );

=head1 VERSION

    v1.0.0

=head1 DESCRIPTION

The purpose of this class/package is to provide an object-oriented approach at array manipulation

=head1 METHODS

=head2 new

Provided with an optional array reference or an array object such as L<Module::Generic::Array>, this will create a new object and return it.

=head2 as_string

Returns the array as string, which is essentially the same as C<"@array">

It takes an optional boolean value that, if true, will sort the array before.

=head2 as_hash

Returns an hash reference with the keys being the array elements and the hash values their offset value.

It takes an optional hash of options:

=over 4

=item I<start_from>

If true, the offset values will start from the number provided and not 0, as it is the case by default.

=back

Example:

    my $a = Module::Generic::Array->new( [qw( Jack John Peter )] );
    my $h = $a->as_hash({ start_from => 1 });
    # $h now is:
    {
        Jack => 1,
        John => 2,
        Peter => 3,
    }

=head2 clone

Creates a clone of the current array object and returns it.

=head2 delete

Provided with an offset value and an optional length, and this will remove data from the array at the given offset and for the given length.

If no given length is provided, it removes all entries from the offset until the end.

It returns a list of elements removed in list context or a new array object of it in scalar context.

See also L</splice>

=head2 each

Provided with a code reference such as a reference to a subroutine, and this will execute the code passing it the array offset and the current value as the 2 arguements. The current value is also accessible with C<$_>

    $a->each(sub
    {
        print( "I got $_\n" );
        # could also write:
        # print( "I got $_[1] at offset $_[0]\n" );
    });

To exit the loop, return C<undef()>, for example:

    $a->each(sub
    {
        return if( $_ eq $not_this_one );
        print( "ok, this one\n" );
    });

=head2 exists

Provided with a value and this returns the number of match, as an L<Module::Generic::Number> object, if it is found in the array, or false otherwise.

=head2 first

Returns the first element of the array, if any. If there are none, to ensure chaining will work, it will return a L<Module::Generic::Null> object.

=head2 for

Provided with a subroutine reference and this will call the subroutine reference, passing it the offset number and the corresponding array value.

    $ar->for(sub
    {
        my( $i, $val ) = @_;
        # do something
    })

C<$_> is made available and contains the value of C<$val>

It returns the object itself so this can be chained.

To exit the loop, return C<undef()>, for example:

    $a->for(sub
    {
        return if( $_ eq $not_this_one );
        print( "ok, this one\n" );
    });

=head2 foreach

Provided with a subroutine reference and this will call the subroutine reference, passing it the value for each entry in the array.

    $ar->foreach(sub
    {
        my $val = shift( @_ );
        # do something
    })

It returns the object itself so this can be chained.

C<$_> is made available and contains the value of C<$val>

To exit the loop, return C<undef()>, for example:

    $a->foreach(sub
    {
        return if( $_ eq $not_this_one );
        print( "ok, this one\n" );
    });

=head2 get

Provided an integer representing an offset and this returns the corresponding value in the array. Offsets start from 0. A blank value will be treated as 0.

    my $a = Module::Generic::Array->new( [qw( abc def ghi )] );
    $a->get( 1 ); # def
    $a->get( '' ); # abc
    $a->get( undef() ); # abc
    $a->get( -1 ); # ghi

See also L</index>

=head2 grep

Provided with some data, and this will do a grep on the array.

If the data provided is a code reference or a reference to a subroutine, the code reference will be called for each array entry, and C<$_> will also be available for each entry.

If the data is a regular expression, each array entry is tested against it.

It returns a list of matches found in ilst context and a new L<Module::Generic::Array> in scalar context.

=head2 has

This is an alias for L</exists>

=head2 index

Provided with an index of an element in the array and this returns its corresponding value.

It takes an integer and this ensures the value used is an integer by applying L<perlfunc/int>

    my $a = Module::Generic::Array->new( [qw( John Jack Peter )] );
    $a->index( 1 ); # returns Jack

If there is nothing at the given offset, possibly because the array is smaller, then this would return undef.

=head2 iterator

This returns a new iterator to cycle through all the array items using iterator's method, such as L<Module::Generic::Iterator/next> and L<Module::Generic::Iterator/prev>. Each iterator element is an L<Module::Generic::Iterator::Element> object

    my $i = $a->iterator;
    while( $i->has_next )
    {
        my $elem = $i->next;
        my $value = $elem->value;
        # Get the next element relative to our element
        printf( "Next value is: %s at offset %d\n", $elem->next, $elem->next->pos  );
    }

=head2 join

Provided with a string, or expression just as documented in L<perlfunc/"join"> and this will return a string as an L<<Module::Generic::Scalar> object.

=head2 keys

This works as documented in L<perlfunc/"keys"> and returns a list of offset values for each entry in the array.

=head2 last

Returns the last element of the array. If there are none, instead it will return a L<Module::Generic::Null> to ensure chaining will still work.

=head2 length

Returns the size of the array, starting from 1, as a L<Module::Generic::Number> object.

This is different from L</size> that returns value from 0 and -1 if the array is empty.

=head2 list

Reeturns the array as a list

    my $a = Module::Generic::Array->new( [qw( Joe John Mary )] );
    print( "@$a" ); # Joe John Mary
    my @people = $a->list; # @people now is ( "Joe", "John", "Mary" )

=head2 map

Provided with a reference to a subroutine and this will call the subroutine for each element of the array and return a list in list context or a new L<Module::Generic::Array> otherwise.

For each iteration of the array, C<$_> is made available.

    print( $a->map(sub{ $_->value })->join( "\n" ), "\n" );

=head2 pop

Returns the last entry in the array.

=head2 pos

Provided with some value (references are ok too), and this will return the position of it in the array, or undef if nothing was found.

    my $a = Module::Generic::Array->new( [qw( John Jack Peter )] );
    my $offset = $a->pos( 'Jack' ); # returns 1
    $a->pos( 'Bob' ); # Returns undef
    my $hash = { first_name => 'John', last_name => 'Doe' };
    $a->push( $hash );
    $a->pos( $hash ); # Returns 3

Note that it returns the position in the array of the first occurrence found. Maybe I should consider returning a list of all occurrences in list context?

=head2 push

Provided with some data and this adds it at the end of the array.

=head2 push_arrayref

Provided with an array reference, and this add all its entry at the end of the array.

    my $ar = Module::Generic::Array->new( [qw( John Joe Mary )]);
    $ar->push_arrayref( [qw( Jack Peter )] );
    print( $ar->join( "," ), "\n" );
    # Now prints: John, Joe, Mary, Jack, Peter

=head2 reset

This empty the array, just like L</"undef">

=head2 reverse

Returns a the array in reverse order in list context or a new L<Module::Generic::Array> object of it in scalar context.

=head2 scalar

Returns the size of the array. It basically calls L</length>

=head2 set

Provided with an array, an array reference or an array-based object and this replaces all the data in the current object by the ones provided.

Note that if an array object is provided, it will copy the content of that object and not set the array object itself.

    $a->set( qw( John Jack Peter ) ); # Using an array of elements
    $a->set( [qw( John Jack Peter )] ); # Using an array reference of elements
    $a->set( $a2 ); # Using another array object, whatever its class may be

=head2 shift

Remove the first entry and returns it.

=head2 size

Returns the size of the array starting from 0, and -1 if the array is empty, as a L<Module::Generic::Number> object.

This is equivalent to the perl variable C<$#> as documented in L<perldata>. It returns the last index in the array.

This is different from L</length> that returns value from 1 and 0 if the array is empty.

=head2 sort

Sort the array and return the new array as a list in list context or a new L<Module::Generic::Array> object in scalar context.

=head2 splice

Takes the same arguments as the L<perlfunc/"splice"> function, but its return value is different.

If L</splice> is called to add new element, the array object is returned to allow chaining.

If no argument is provided, it just empties the array and return the array object is returned to allow chaining.

When offset and/or length are provided, it returns the list of elements found.

=head2 split

Just like the normal L<perlfunct/"split"> function, it takes a string or expression and split the data provided into a list of elements.

It returns the list in list context, and returns a new L<Module::Generic::Array> object in scalar context.

=head2 undef

Just like L</"reset">, this empty the array.

=head2 unshift

This add the given values at the beginning of the array.

=head2 values

Get a list of all the array values and return a list in list context or a ne L<Module::Generic::Array> object in scalar context.

=head1 SEE ALSO

L<Module::Generic::Scalar>, L<Module::Generic::Number>, L<Module::Generic::Boolean>, L<Module::Generic::Hash>, L<Module::Generic::Dynamic>

=head1 AUTHOR

Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>

=head1 COPYRIGHT & LICENSE

Copyright (c) 2000-2020 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated
files under the same terms as Perl itself.

=cut

