# NAME

Object::ArrayType::New - Inject constants & constructors for ARRAY-type objects

# SYNOPSIS

    package MyObject;
    use strict; use warnings;
    use Object::ArrayType::New
      [ foo => 'FOO', bar => 'BAR' ];
    sub foo     { shift->[FOO] }
    sub bar     { shift->[BAR] ||= [] }

    package main;
    my $obj = MyObject->new(foo => 'baz');
    my $foo = $obj->foo; # baz
    my $bar = $obj->bar; # []

# DESCRIPTION

ARRAY-backed objects are light and fast, but obviously slightly more
complicated to cope with than just stuffing key/value pairs into a HASH.
The easiest way to keep track of where things live is to set up some named
constants to index into the ARRAY -- you can access your indexes by name,
and gain compile-time typo checking as an added bonus.

A common thing I find myself doing looks something like:

    package MySimpleObject;
    use strict; use warnings;

    sub TAG () { 0 }
    sub BUF () { 1 }
    # ...

    sub new {
      my $class = shift;
      my %params = @_ > 1 ? @_ : %{ $_[0] };
      bless [
        $params{tag},             # TAG
        ($params{buffer} || [])   # BUF
        # ...
      ], $class
    }
    sub tag     { shift->[TAG] }
    sub buffer  { shift->[BUF] }
    # ...

... when I'd rather be doing something more like the ["SYNOPSIS"](#SYNOPSIS).

This tiny module takes an ARRAY of pairs mapping a `new()` parameter name to the
name of a constant. The constant represents the item's position in the
object's backing ARRAY.

If the constant's name is boolean false, the uppercased parameter name is
used as the name of the constant:

    use Object::ArrayType::New
      [ foo => '', bar => '' ];
    # same as foo => 'FOO', bar => 'BAR'

If the parameter's name is boolean false, there is no construction-time
parameter. The constant is installed and the appropriate position in the
backing ARRAY is set to `undef` at construction time; this can be useful for
private attributes:

    use Object::ArrayType::New
      [ foo => 'FOO', '' => 'BAR' ];
    sub foo  { shift->[FOO] ||= 'foo' }
    sub _bar { shift->[BAR] ||= [] }

An appropriate constructor is generated and installed, as well as constants
that can be used within the class to index into the `$self` object.

The generated constructor takes parameters as either a list of pairs or a
single HASH. Parameters not specified at construction time are `undef`.

That's it; no accessors, no defaults, no type-checks, no required attributes,
nothing fancy. [Class::Method::Modifiers](http://search.cpan.org/perldoc?Class::Method::Modifiers) may be convenient there; the above
raw Perl example could be written something like:

    use Object::ArrayType::New [ tag => '', buffer => 'BUF' ];
    sub tag    { shift->[TAG] }
    sub buffer { shift->[BUF] }
    use Class::Method::Modifers;
    around new => sub {
      my ($orig, $class) = splice @_, 0, 2;
      my $self = $class->$orig(@_);
      $self->[BUF] = [] unless defined $self->[BUF];
      $self
    };

if `$ENV{OBJECT_ARRAYTYPE_DEBUG}` is true, generated code is printed to
STDERR before being evaluated.

Constants aren't currently sanity-checked ahead of time; attempting to use
invalid identifiers will result in vague 'Illegal declaration ...' failures.

# AUTHOR

Jon Portnoy <avenj@cobaltirc.org>
