GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
List::Objects::WithUtils(3) User Contributed Perl Documentation List::Objects::WithUtils(3)

List::Objects::WithUtils - List objects, kitchen sink included

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

  # Import all object constructor functions:
  #   array immarray array_of immarray_of
  #   hash immhash hash_of immhash_of
  use List::Objects::WithUtils;

  # Import all of the above plus autoboxing:
  use List::Objects::WithUtils ':all';
  # Same as above, but shorter:
  use Lowu;

  # 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 $want_idx = array(
    +{ id => '400', user => 'bob' },
    +{ id => '600', user => 'suzy' },
    +{ id => '700', user => 'fred' },
  )->first_index(sub { $_->{id} > 500 });

  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

  # 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');

  # Arrays inflate to hash objects:
  my $items = array( qw/ foo bar baz/ )->map(sub { $_ => 1 })->inflate;
  if ($items->exists('foo')) {
    # ...
  }

  # Hashes inflate to simple objects with accessors:
  my $obj = $hash->inflate;
  $snacks = $obj->snacks;

  # Methods returning 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 == qr/snacks/ ) {
    # ... hash has key(s) matching /snacks/ ...
  }
  if ( $hash->values->all_items > 10 ) {
    # ... all hash values greater than 10 ...
  }

  # Type-checking arrays via Type::Tiny:
  use Types::Standard -all;
  my $int_arr = array_of Int() => 1 .. 10;

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

  # 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
  }

A set of roles and classes defining an object-oriented interface to Perl hashes and arrays with useful utility methods, junctions, type-checking ability, and optional autoboxing. Originally derived from Data::Perl.

The included objects are useful as-is but are largely intended for use as data container types for attributes. This lends a more natural object-oriented syntax; these are particularly convenient in combination with delegated methods, as in this example:

  package Some::Thing;
  use List::Objects::WithUtils;
  use Moo;

  has items => (
    is      => 'ro',
    builder => sub { array },
    handles => +{
      add_items   => 'push',
      get_items   => 'all',
      items_where => 'grep',
    },
  );

  # ... later ...
  my $thing = Some::Thing->new;
  $thing->add_items(@more_items);
  # Operate on all positive items:
  for my $item ($thing->items_where(sub { $_ > 0 })->all) {
    ...
  }

List::Objects::Types provides Type::Tiny-based types & coercions matching the list objects provided by this distribution. These integrate nicely with typed or untyped list objects:

  package Accounts;
  use List::Objects::Types -types;
  use Moo 2;

  has usergroups => (
    is        => 'ro',
    # +{ $group => [ [ $usr => $id ], ... ] }
    # Coerced to objects all the way down:
    isa       => TypedHash[ TypedArray[ArrayObj] ],
    coerce    => 1,
    builder   => sub { +{} },
  );

  # ... later ...
  my $users_in_grp = $accts->usergroups
    ->get($some_group)
    ->grep(sub { $_[0]->get(0) });

Arrays

array (List::Objects::WithUtils::Array) provides basic mutable ARRAY-type objects. 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; using immutable arrays promotes safer programming patterns.

array_of provides Type::Tiny-compatible type-checking array objects that can coerce and check their values as they are added; see List::Objects::WithUtils::Array::Typed.

immarray_of provides immutable type-checking arrays; see List::Objects::WithUtils::Array::Immutable::Typed.

Hashes

hash is the basic mutable HASH-type object imported from List::Objects::WithUtils::Hash; see List::Objects::WithUtils::Role::Hash for documentation.

immhash provides immutable (restricted) hashes; see List::Objects::WithUtils::Hash::Immutable.

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

immhash_of provides immutable type-checking hashes; see List::Objects::WithUtils::Hash::Immutable::Typed.

A bare import list ("use List::Objects::WithUtils;") will import all of the object constructor functions described above; they can also be selectively imported, e.g.:

  use List::Objects::WithUtils 'array_of', 'hash_of';

Importing autobox lexically enables List::Objects::WithUtils::Autobox, which provides List::Objects::WithUtils::Array or List::Objects::WithUtils::Hash methods for native ARRAY and HASH types.

Importing all or :all will import all of the object constructors and additionally turn autobox on; "use Lowu;" is a shortcut for importing all.

Most methods belonging to these objects are heavily micro-optimized -- at the cost of useful error handling.

Since there are few built-in argument checks, a mistake in your code can frequently lead to slightly cryptic errors from the perl side:

  > my $pos;  # whoops, I'm still undefined later:
  > if ($arr->exists($pos)) { ... }
  Use of uninitialized value in numeric le (<=) at $useless_lib_lineno

... in which case Devel::Confess is likely to improve your quality of life by providing a real backtrace:

  $ perl -d:Confess my_app.pl
  Use of uninitialized value in numeric le (<=) at ...
    [...]::Array::exists(ARRAY(0x8441068), undef) called at ...

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;
  # Act like List::Objects::WithUtils::Array:
  with 'List::Objects::WithUtils::Role::Array',
       'List::Objects::WithUtils::Role::Array::WithJunctions';

  # One 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' }

  # ... add/override methods ...

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

List::Objects::WithUtils::Role::Array::WithJunctions for documentation on "array()" junction-returning 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::Array::Immutable::Typed for more on "immarray_of()" immutable type-checking arrays.

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

List::Objects::WithUtils::Hash::Immutable for more on "immhash()" immutable hashes.

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

List::Objects::WithUtils::Hash::Immutable::Typed for more on "immhash_of()" immutable 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.

Jon Portnoy <avenj@cobaltirc.org>

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 originally inspired by Const::Fast by Leon Timmermans (CPAN: LEONT), but now use "tie".

Junctions are adapted from Perl6::Junction by Carl Franks (CPAN: CFRANKS)

Most of the type-checking code and other useful additions were contributed by Toby Inkster (CPAN: TOBYINK)

A significant portion of this code simply wraps other widely-used modules, especially:

List::Util

List::UtilsBy

Type::Tiny

Inspiration for a few pieces comes from the "classic" (version 0.33) List::MoreUtils.

2016-04-07 perl v5.32.1

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.