NAME
   List::Objects::WithUtils - List objects with useful methods

SYNOPSIS
     ## A small sample; consult the description, below, for links to
     ## extended documentation

     # Import selectively:
     use List::Objects::WithUtils 'array';

     # Import 'array()', 'immarray()', 'hash()' object constructors:
     use List::Objects::WithUtils;

     # Import all functions:
     use List::Objects::WithUtils ':functions';

     # Import all of the above plus autoboxing:
     use List::Objects::WithUtils ':all';
     # Same, but via convenience shortcut:
     use Lowu;

     # Some simple chained array operations, eventually returning a plain list
     # Most methods returning lists return new objects; chaining is easy:
     array(qw/ aa Ab bb Bc bc /)
       ->grep(sub { /^b/i })
       ->map(sub  { uc })
       ->uniq
       ->all;   # ( 'BB', 'BC' )

     # Useful utilities from other list modules are available:
     my $wanted = array(
       +{ id => '200', user => 'bob' },
       +{ id => '400', user => 'suzy' },
       +{ id => '600', user => 'fred' },
     )->first(sub { $_->{id} > 500 });

     my $sum = array( 1, 2, 3 )->reduce(sub { $_[0] + $_[1] });  # 6

     my $itr = array( 1 .. 7 )->natatime(3);
     while ( my @nextset = $itr->() ) {
       ...
     }

     my $meshed = array(qw/ a b c d /)
       ->mesh( array(1 .. 4) )
       ->all;   # ( 'a', 1, 'b', 2, 'c', 3, 'd', 4 )

     my ($evens, $odds) = array( 1 .. 20 )
       ->part(sub { $_[0] & 1 })
       ->all;

     my $sorted = array(
       +{ name => 'bob',  acct => 1 },
       +{ name => 'fred', acct => 2 },
       +{ name => 'suzy', acct => 3 },
     )->sort_by(sub { $_->{name} });

     # array() objects are mutable:
     my $mutable = array(qw/ foo bar baz /);
     $mutable->insert(1, 'quux');
     $mutable->delete(2);

     # ... or use immarray() immutable arrays:
     my $static = immarray( qw/ foo bar baz / );
     $static->set(0, 'quux');  # dies
     $static->[0] = 'quux';    # dies
     push @$static, 'quux';    # dies

     # Simple hash operations; construct a hash:
     my $hash  = hash( foo => 'bar', snacks => 'cake' );

     # You can set multiple keys in one call:
     $hash->set( foobar => 'baz', pie => 'cherry' );
     # ... which is useful for merging in another (plain) hash:
     my %foo = ( pie => 'pumpkin', snacks => 'cheese' );
     $hash->set( %foo );
     # ... or another hash object:
     my $second = hash( pie => 'key lime' );
     $hash->set( $second->export );

     # Retrieve one value as a simple scalar:
     my $snacks = $hash->get('snacks');

     # ... or retrieve multiple values as an array-type object:
     my $vals = $hash->get('foo', 'foobar');

     # Take a hash slice of keys, return a new hash object
     # consisting of the retrieved key/value pairs:
     my $slice = $hash->sliced('foo', 'pie');

     # Chained method examples; methods that return multiple values
     # typically return new array-type objects:
     my @match_keys = $hash->keys->grep(sub { m/foo/ })->all;
     my @match_vals = $hash->values->grep(sub { m/bar/ })->all;

     my @sorted_pairs = hash( foo => 2, bar => 3, baz => 1)
       ->kv
       ->sort_by(sub { $_->[1] })
       ->all;  # ( [ baz => 1 ], [ foo => 2 ], [ bar => 3 ] )

     # Perl6-inspired Junctions:
     if ( $hash->keys->any_items eq 'snacks' ) {
       ...
     }
     if ( $hash->values->all_items > 10 ) {
       ...
     }

     # Type-checking arrays:
     use List::Objects::WithUtils 'array_of';
     use Types::Standard -all;
     my $int_arr = array_of( Int, 1 .. 10 );

     # Type-checking hashes:
     use List::Objects::WithUtils 'hash_of';
     use Types::Standard -all;
     my $int_hash = hash_of( Int, foo => 1, bar => 2 );

     # Hashes can be inflated to objects:
     my $obj = $hash->inflate;
     $snacks = $obj->snacks;

     # Native list types can be autoboxed:
     use List::Objects::WithUtils 'autobox';
     my $foo = [ qw/foo baz bar foo quux/ ]->uniq->sort;
     my $bar = +{ a => 1, b => 2, c => 3 }->values->sort;

     # Autoboxing is lexically scoped like normal:
     { no List::Objects::WithUtils::Autobox;
       [ 1 .. 10 ]->shuffle;  # dies
     }

DESCRIPTION
   A set of roles and classes defining an object-oriented interface to Perl
   hashes and arrays with useful utility methods, junctions, and optional
   autoboxing.

   Originally derived from Data::Perl.

   array is imported from List::Objects::WithUtils::Array and creates a new
   ARRAY-type object. Behavior is defined by
   List::Objects::WithUtils::Role::Array; look there for documentation on
   available methods.

   immarray is imported from List::Objects::WithUtils::Array::Immutable and
   operates much like an array, except methods that mutate the list are not
   available and the backing ARRAY is marked read-only; using immutable
   arrays promotes safer functional patterns.

   hash is imported from List::Objects::WithUtils::Hash; see
   List::Objects::WithUtils::Role::Hash for documentation.

   Importing autobox lexically enables List::Objects::WithUtils::Autobox,
   providing methods for native ARRAY and HASH types.

   A bare import list ("use List::Objects::WithUtils;") will import the
   "array", "immarray", and "hash" functions.

   Importing array_of gives you Type::Tiny-compatible type-checking array
   objects; see List::Objects::WithUtils::Array::Typed.

   Importing hash_of gives you Type::Tiny-compatible type-checking hash
   objects; see List::Objects::WithUtils::Hash::Typed.

   Importing functions or :functions will import all of the above.

   Importing all or :all will import all of the above and additionally turn
   autobox on, as will the shortcut "use Lowu;" (as of 1.003).

   Why another object-oriented list module?

   There are a fair few object-oriented approaches to lists on CPAN, none
   of which were quite what I needed. Data::Perl comes the closest -- but
   is primarily targetting MooX::HandlesVia and could not guarantee a
   stable API at the time this was written (plus, I don't need the other
   data types).

   This module aims to provide a consistent, natural interface to hashes
   and arrays exclusively, with convenient access to common tools. The
   interface is expected to remain stable; methods may be added but are not
   expected to be removed (or experience incompatible interface changes,
   barring serious bugs).

SEE ALSO
   List::Objects::WithUtils::Role::Array for documentation on the basic set
   of "array()" methods.

   List::Objects::WithUtils::Role::WithJunctions for documentation on
   "array()" junction-returning methods.

   List::Objects::WithUtils::Role::Hash for documentation regarding
   "hash()" methods.

   List::Objects::WithUtils::Array::Immutable for more on "immarray()"
   immutable arrays.

   List::Objects::WithUtils::Array::Typed for more on "array_of()"
   type-checking arrays.

   List::Objects::WithUtils::Hash::Typed for more on "hash_of()"
   type-checking hashes.

   List::Objects::WithUtils::Autobox for details on autoboxing.

   The Lowu module for a convenient importer shortcut.

   List::Objects::Types for relevant Type::Tiny types.

   MoopsX::ListObjects for integration with Moops class-building sugar.

 Subclassing
   The importer for this package is somewhat flexible; a subclass can
   override import to pass import tags and a target package by feeding this
   package's "import()" a HASH:

     # Subclass and import to target packages (see Lowu.pm f.ex):
     package My::Defaults;
     use parent 'List::Objects::WithUtils';
     sub import {
       my ($class, @params) = @_;
       $class->SUPER::import(
         +{
           import => [ 'autobox', 'array', 'hash' ],
           to     => scalar(caller)
         }
       )
     }

   Functionality is mostly defined by Roles. For example, it's easy to
   create your own array class with new methods:

     package My::Array::Object;
     use Role::Tiny::With;
     with 'List::Objects::WithUtils::Role::Array',
          'List::Objects::WithUtils::Role::WithJunctions';

     # An easy way to add your own functional interface:
     use Exporter 'import';  our @EXPORT = 'my_array';
     sub my_array { __PACKAGE__->new(@_) }

     # ... add/override methods ...

   ... in which case you may want to also define your own hash subclass
   that overrides "array_type" to produce your preferred arrays:

     package My::Hash::Object;
     use Role::Tiny::With;
     with 'List::Objects::WithUtils::Role::Hash';

     use Exporter 'import';  our @EXPORT = 'my_hash';
     sub my_hash { __PACKAGE__->new(@_) }

     sub array_type { 'My::Array::Object' }

     # ...

AUTHOR
   Jon Portnoy <[email protected]>

   Licensed under the same terms as Perl.

   The original Array and Hash roles were derived from Data::Perl by
   Matthew Phillips (CPAN: MATTP), haarg, and others.

   Immutable array objects were inspired by Const::Fast.

   Junctions are adapted from Perl6::Junction by Carl Franks.

   Many of the useful type-checking bits were contributed by Toby Inkster
   (CPAN: TOBYINK).

   Much of this code simply wraps other widely-used modules, including:

   List::Util

   List::MoreUtils

   List::UtilsBy