=encoding utf8

=head1 NAME

List::oo - object interface to list (array) methods

=head1 SYNOPSIS

Connecting multiple list I<functions> together "reads" from right to
left (starting with the data input way over on the right.)

This module provides a chainable method interface to array objects,
which can be a bit more readable when multiple operations are involved.

This

  print join(' ', map({"|$_|"} qw(a b c))), "\n";

becomes:

  use List::oo qw(L);
  print L(qw(a b c))->map(sub {"|$_|"})->join(' '), "\n";

There is definitely some cost of execution speed.  This is just an
experiment.  Comments and suggestions welcome.


=cut

=head1 Constructors

=head2 new

  $l = List::oo->new(@array);


=cut

=head2 L

  $l = L(@array);


=cut

=head1 Strange Constructors

This is only here because you so frequently need to start with a string
op and L(split(...)) is ugly.

Aside:  I'm not sure I really like this as an interface point.  The need
to use qr// is at least a little annoying.

=head2 Split

  my $l = Split(qr/\s+/, $string);


=cut

=head1 Convenience Functions

=head2 F

Declare a subroutine.

  F{...};

See also L<lambda>, which lets you use C<λ{}> instead.

=over

=item About the C<sub {...}> syntax

Sadly, perl5 does not allow prototypes on methods.  Thus, we cannot use
the undecorated block syntax as with

  map({...} @list);

Rather, you must use the explicit C<sub {...}> syntax

  $l->map(sub {...});

Or, use the C<F{}> or C<λ{}> shortcuts.

  use List::oo qw(F);
  ...
  $l->map(F{...});

With L<lambda>

  use lambda;
  ...
  $l->map(λ{...});

(If the above doesn't render as the greek character lambda, your pod
viewer is not playing nice.)

=back


=cut

=head1 List Methods

These methods are mostly analogous to the perl builtins.  Where the
builtin would return a list, we return a List::oo object.  Where the
builtin returns a scalar or some data which was not the primary list
(e.g. C<push>, C<pop>, C<splice>, etc.), you'll find some iI<foo>()
methods (the 'i' prefix is for 'inline'.)

=head2 grep

  $l = $l->grep(sub {...});


=cut

=head2 map

  $l = $l->map(sub {...});


=cut

=head2 reverse

  $l = $l->reverse;


=cut

=head2 dice

Does things that can't be done with map.

  $l2 = $l->dice(sub {my @a = @_; ... return(@a);});

Feeds @$l into sub, which should return a perl list.  Puts the results
in a new List::oo object.

The purpose is simply to allow you to write an unbroken chain when you
need to feed the entire list through some function which doesn't operate
per-element.

Without this, you would have to break the chain of thought

  L(that_function($l->map(\&fx)->l))->map(\&fy);

With dice, simply insert it where it is needed.

  $l->map(\&fx)->dice(sub {that_function(@_)})->map(\&fy);

Note that in contrast to map() and grep() methods, dice() does not
define the $_ variable.

What sort of functions need the whole list?  Say you want to reverse
the front and back half of a list, or maybe break a list of 20 items
into 5 references of 4 items each.  See the tests for examples.


=cut

=head2 sort

A lot like CORE::sort.

  $l->sort;

  $l->sort(sub {$a <=> $b});

Unfortunately, we don't get the sort C<$a>/C<$b> package variable magic.
So, I set your package's $a and $b just like sort would.  This means you
might get "used only once" warnings, but you can silence these with:

  use List::oo qw($a $b);

The C<$a> and C<$b> imports have no other effect.


=cut

=head2 splice

Splices into @$l and returns the removed elements (or last element in
scalar context) ala CORE::splice.

  $l->splice($offset, $length, @list);

With no replacement:

  $l->splice($offset, $length);

Remove everything from $offset onward

  $l->splice($offset);

Empties the list

  $l->splice;


=cut

=head1 Head and Tail Methods

=head2 push

Returns the new length of the list.

  $l->push(@stuff);


=cut

=head2 pop

Removes and returns the last item.

  $l->pop;


=cut

=head2 shift

Removes and returns the first item.

  $l->shift;


=cut

=head2 unshift

Prepends @stuff to @$l and returns the new length of @$l.

  $l->unshift(@stuff);


=cut

=head1 Inlined Methods

If you want to keep chaining calls together (and don't need to retrieve
the pop/shift/splice data.)

=head2 ipush

  $l->map(sub {...})->ipush($val)->map(sub {...});

=head2 ipop

  $l->map(sub {...})->ipop->map(sub {...});

=head2 ishift

  $l->map(sub {...})->ishift->map(sub {...});

=head2 iunshift

  $l->map(sub {...})->iunshift($val)->map(sub {...});

=head2 isplice

  $l->map(sub {...})->isplice($offset, ...)->map(sub {...});


=cut

=head2 wrap

Add new values to the start and end.

  $l = $l->wrap($head,$tail);

Is just:

  $l->iunshift($head)->ipush($tail);


=cut

=head1 Additions to List::MoreUtils

The lack of prototypes means I can't do everything that List::MoreUtils
does in exactly the same way.  I've chosen to make the bindings to
multi-list methods take only single lists and added mI<foo>() methods
here.

=head2 mmesh

Meshes @$l, @a, @b, @c, ...

  my $l = $l->mmesh(\@a, \@b, \@c, ...);


=cut

=head2 meach_array

Just the binding to List::MoreUtils::each_arrayref;

  my $iterator = $l->meach_array(\@a, \@b, \@c);


=cut

=head1 Give Me Back My List

You can wrap the call chain in @{} or use one of the following methods.

=head2 flatten

If you really like to type.

  @list = $l->flatten;

=head2 l

The l is pretty flat and is the lowercase (less special) version of our
terse constructor L().

  @list = $l->l;


=cut

=head1 Scalar Result Methods

These only work at the end of a chain.

=head2 join

  $string = $l->join("\n");


=cut

=head2 length

Length of the list.

  $l->length;


=cut

=head1 List::Util / List::MoreUtils

The following method documentation is autogenerated along with the
wrappers of functions from List::Util and List::MoreUtils.  The
supported usage is shown (in some cases, these methods only support a
subset of the function usage (due to the lack of method prototype
support.)

The clusters of sigils (e.g. C<l=&l>) are included as a shorthand
reference.  These sigils are what drive the code generation (see the
source of List::oo::Extras and the build_extras.pl tool in the source
repository for the dirty details.)  The sigil on the left of the '='
represents the return value, the sigils on the right of the '='
represent what is passed to the wrapped function.

  l - a List::oo object (the $self when found on the right)
  L - an array of List::oo objects
  $ - a scalar
  @ - an array
  & - a subroutine reference (λ)

See List::Util and List::MoreUtils for more info.

=head3 Aliases

=over

=item each_arrayref

alias to L</meach_array>

=item first_index

alias to L</firstidx>

=item first_value

alias to L</firstval>

=item last_index

alias to L</lastidx>

=item last_value

alias to L</lastval>

=item zip

alias to L</mesh>

=back

=head3 Methods

=over

=item after

C<l=&l>

  my $list_obj = $list->after($block);

See L<List::MoreUtils::after()|List::MoreUtils/item after>

=item after_incl

C<l=&l>

  my $list_obj = $list->after_incl($block);

See L<List::MoreUtils::after_incl()|List::MoreUtils/item after_incl>

=item all

C<$=&l>

  my $answer = $list->all($block);

See L<List::MoreUtils::all()|List::MoreUtils/item all>

=item any

C<$=&l>

  my $answer = $list->any($block);

See L<List::MoreUtils::any()|List::MoreUtils/item any>

=item apply

C<l=&l>

  my $list_obj = $list->apply($block);

See L<List::MoreUtils::apply()|List::MoreUtils/item apply>

=item before

C<l=&l>

  my $list_obj = $list->before($block);

See L<List::MoreUtils::before()|List::MoreUtils/item before>

=item before_incl

C<l=&l>

  my $list_obj = $list->before_incl($block);

See L<List::MoreUtils::before_incl()|List::MoreUtils/item before_incl>

=item each_array

C<$=l@>

  my $answer = $list->each_array(@list);

See L<List::MoreUtils::each_array()|List::MoreUtils/item each_array>

=item false

C<$=&l>

  my $answer = $list->false($block);

See L<List::MoreUtils::false()|List::MoreUtils/item false>

=item first

C<$=l>

  my $answer = $list->first();

See L<List::Util::first()|List::Util/item first>

=item firstidx

C<$=&l>

  my $answer = $list->firstidx($block);

See L<List::MoreUtils::firstidx()|List::MoreUtils/item firstidx>

=item firstval

C<$=&l>

  my $answer = $list->firstval($block);

See L<List::MoreUtils::firstval()|List::MoreUtils/item firstval>

=item indexes

C<l=&l>

  my $list_obj = $list->indexes($block);

See L<List::MoreUtils::indexes()|List::MoreUtils/item indexes>

=item insert_after

C<l=&$l>

  my $list_obj = $list->insert_after($block, $var1);

See L<List::MoreUtils::insert_after()|List::MoreUtils/item insert_after>

=item insert_after_string

C<l=$$l>

  my $list_obj = $list->insert_after_string($var1, $var2);

See L<List::MoreUtils::insert_after_string()|List::MoreUtils/item insert_after_string>

=item lastidx

C<$=&l>

  my $answer = $list->lastidx($block);

See L<List::MoreUtils::lastidx()|List::MoreUtils/item lastidx>

=item lastval

C<$=&l>

  my $answer = $list->lastval($block);

See L<List::MoreUtils::lastval()|List::MoreUtils/item lastval>

=item max

C<$=l>

  my $answer = $list->max();

See L<List::Util::max()|List::Util/item max>

=item maxstr

C<$=l>

  my $answer = $list->maxstr();

See L<List::Util::maxstr()|List::Util/item maxstr>

=item mesh

C<l=l@>

  my $list_obj = $list->mesh(@list);

See L<List::MoreUtils::mesh()|List::MoreUtils/item mesh>

=item min

C<$=l>

  my $answer = $list->min();

See L<List::Util::min()|List::Util/item min>

=item minmax

C<@=l>

  my @answers = $list->minmax();

See L<List::MoreUtils::minmax()|List::MoreUtils/item minmax>

=item minstr

C<$=l>

  my $answer = $list->minstr();

See L<List::Util::minstr()|List::Util/item minstr>

=item natatime

C<$=$l>

  my $answer = $list->natatime($var1);

See L<List::MoreUtils::natatime()|List::MoreUtils/item natatime>

=item none

C<$=&l>

  my $answer = $list->none($block);

See L<List::MoreUtils::none()|List::MoreUtils/item none>

=item notall

C<$=&l>

  my $answer = $list->notall($block);

See L<List::MoreUtils::notall()|List::MoreUtils/item notall>

=item pairwise

C<l=&l@>

  my $list_obj = $list->pairwise($block, @list);

See L<List::MoreUtils::pairwise()|List::MoreUtils/item pairwise>

=item part

C<L=&l>

  my @list_objs = $list->part($block);

See L<List::MoreUtils::part()|List::MoreUtils/item part>

=item reduce

C<$=&l>

  my $answer = $list->reduce($block);

See L<List::Util::reduce()|List::Util/item reduce>

=item shuffle

C<l=l>

  my $list_obj = $list->shuffle();

See L<List::Util::shuffle()|List::Util/item shuffle>

=item sum

C<$=l>

  my $answer = $list->sum();

See L<List::Util::sum()|List::Util/item sum>

=item true

C<$=&l>

  my $answer = $list->true($block);

See L<List::MoreUtils::true()|List::MoreUtils/item true>

=item uniq

C<l=l>

  my $list_obj = $list->uniq();

See L<List::MoreUtils::uniq()|List::MoreUtils/item uniq>

=back

=head1 AUTHOR

Eric Wilhelm @ <ewilhelm at cpan dot org>

http://scratchcomputing.com/

=over

=item Thanks to

Jim Keenan for contributions to the test suite.

=back

=head1 BUGS

If you found this module on CPAN, please report any bugs or feature
requests through the web interface at L<http://rt.cpan.org>.  I will be
notified, and then you'll automatically be notified of progress on your
bug as I make changes.

If you pulled this development version from my /svn/, please contact me
directly.

=head1 COPYRIGHT

Copyright (C) 2006-2007 Eric L. Wilhelm, All Rights Reserved.

=head1 NO WARRANTY

Absolutely, positively NO WARRANTY, neither express or implied, is
offered with this software.  You use this software at your own risk.  In
case of loss, no person or entity owes you anything whatsoever.  You
have been warned.

=head1 LICENSE

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

=head1 SEE ALSO

  EO::Array


=cut

