NAME
OP::Array - Array object class
DESCRIPTION
Extends OP::Object to handle Perl ARRAY refs as OP Objects. Provides constructor, getters, setters, "Ruby-esque" collection, and other methods which one might expect an Array object to respond to.
INHERITANCE
This class inherits additional class and object methods from the following packages:
OP::Class > OP::Object > OP::Array
SYNOPSIS
use OP::Array;
my $emptyList = OP::Array->new();
my $arrayFromList = OP::Array->new(@list); # Makes new ref
my $arrayFromRef = OP::Array->new($ref); # Keeps orig ref
METHODS
Public Class Methods
$class->new(@list)
Instantiate a new OP::Array. Accepts an optional array or array reference as a prototype object
Usage is cited in the SYNOPSIS section of this document.
$class->assert(OP::Type $memberType, *@rules)
Return a new OP::Type::Array instance.
To permit multiple values of a given type, just wrap an
Array()
assertion around any other assertion.Each element in the stored array lives in a dynamically subclassed linked table, with foreign key constraints against the parent table.
# # File: Example.pm # use OP; create "OP::Example" => { # # An array of strings: # someArr => OP::Array->assert( OP::Str->assert() ), ... };
In Caller:
#!/bin/env perl # # File: somecaller.pl # use strict; use warnings; use OP::Example; my $exa = OP::Example->spawn("Array Example"); $exa->setSomeArr("Foo", "Bar", "Rebar", "D-bar"); $exa->save();
Nested Arrays:
Array()
can be wrapped around otherArray()
assertions, for cases where multi-dimensional arrays are needed. Each assertion has independent rules:# # File: Example.pm # use OP; create "OP::Example" => { # # Fancy... a 3x3 matrix of integers with per-element enforcement of # min and max values: # matrix => OP::Array->assert( OP::Array->assert( OP::Int->assert( subtype( min => 0, max => 255 ) ), subtype( size => 3, ), ), subtype( size => 3 ) ), # ... };
In caller:
#!/bin/env perl # # File: somecaller.pl # use strict; use warnings; use OP::Example; my $example = OP::Example->spawn("Matrix Example"); # # Data looks like this: # $example->setMatrix( [255, 127, 63], [69, 69, 69] [42, 23, 5] ); $example->save();
Public Instance Methods
$array->get($index)
Get the received array index. Functionally the same as $ref->[$index].
my $array = OP::Array->new( qw| foo bar | ); my $foo = $array->get(0); my $bar = $array->get(1);
$array->set($index, $value)
Set the received array index to the received value. Functionally the same as $ref->[$index] = $value.
my $array = OP::Array->new( qw| foo bar | ); $array->set(1, "rebar"); # was "bar", now is "rebar"
$array->push(@list)
Object wrapper for Perl's built-in
push()
function. Functionally the same aspush(@$ref, @list)
.my $array = OP::Array->new(); $array->push($something); $array->push( qw| foo bar | );
$array->size()
Object wrapper for Perl's built-in
scalar()
function. Functionally the same asscalar(@$ref)
.my $array = OP::Array->new( qw| foo bar | ); my $size = $array->size(); # returns 2
$array->collect($sub)
$array->collectWithIndex($sub)
yield(item, [item, ...]), emit(item, [item, ...]), return, break
List iterator method.
collect
returns a new array with the results of running the received CODE block once for every element in the original. Returns the yielded/emitted results in a new OP::Array instance.This Perl implementation of
collect
is borrowed from Ruby. OP employs several functions which may finely control the flow of execution.The collector pattern is used throughout OP. The following pseudocode illustrates its possible usage.
my $array = OP::Array->new( ... ); my $sub = sub { my $item = shift; # ... return if $something; # Equivalent to next() break() if $somethingElse; # Equivalent to last() emit($thing1, [$thing2, ...]); # Upstreams $things, # and continues current iteration # ... yield($thing1, [$thing2, ...]); # Upstreams $things, # and skips to next iteration }; my $results = $array->collect($sub);
A simple working example - return a new array containing capitalized versions of each element in the original. Collection is performed using
collect
;each
may be used when there is code to run with no return values.my $array = OP::Array->new( qw| foo bar baz whiskey tango foxtrot | ); my $capped = $array->collect( sub { my $item = shift; yield uc($item) } ); $capped->each( sub { my $item = shift; print "Capitalized array contains item: $item\n"; } );
Collector Control Flow
The flow of the collect sub may be controlled using
return
,yield
,emit
, andbreak
.break
invokes Perl'slast
, breaking execution of thecollect
loop.In the context of the collect sub,
return
is like Perl'snext
or Javascript'scontinue
- that is, it stops execution of the sub in progress, and continues on to the next iteration. Because Perl subs always end with an implicit return, usingreturn
to reap yielded elements is not workable, so we useyield
for this instead. Any arguments toreturn
in this context are ignored.Like
return
,yield
stops execution of the sub in progress, but items passed as arguments toyield
are added to the new array returned bycollect
.emit
adds items to the returned array, but does so without returning from the sub in progress. Emitted items are added to the array returned by the collect sub, just likeyield
, but you may callemit
as many times as needed per iteration, without breaking execution.If nothing is yielded or emitted by the collect sub in an iteration, nothing will be added to the returned array for that item. To yield nothing for an iteration, don't
yield(undef)
, just don'tyield
-- Rather, usereturn
instead, to avoid undefined elements in the returned array.If yielding multiple items at a time, they are added to the array returned by
collect
in a "flat" manner-- that is, no array nesting will occur unless the yielded data is explicitly structured as such.Recap: Return vs Yield vs Emit
yield
adds items to the array returned by the collect sub, in addition to causing Perl to jump ahead to the next iteration, likenext
in afor
loop would. Remember,return
just returns without adding anything to the return array-- use it in cases where you just want to skip ahead without yielding items (ienext
).# # Create a new Array ($quoted) containing quoted elements # from the original, omitting items which aren't wanted. # my $quoted = $array->collect( sub { my $item = shift; print "Have item: $item\n"; return if $item =~ /donotwant/; yield( $myClass->quote($item) ); print "You will never get here.\n"; } ); # # The above was roughly equivalent to: # my $quoted = OP::Array->new(); for my $item ( @{ $array } ) { print "Have item: $item\n"; next if $item =~ /donotwant/; $quoted->push( $myClass->quote($item) ); next; print "You will never get here.\n"; }
emit
adds items to the array returned by the collect sub, but does so without returning (that is, execution of the sub in progress will continue uninterrupted). It's just likepush
ing to an array from inside afor
loop, because that's exactly what it does.The only functional difference between the preceding example for
yield
and the below example foremit
is that usingemit
lets the interpreter get to that finalprint
statement.# # For example, create a new Array ($quoted) containing quoted elements # from the original, omitting items which aren't wanted. # my $quoted = $array->collect( sub { my $item = shift; print "Have item: $item\n"; return if $item =~ /donotwant/; emit( $myClass->quote($item) ); print "You will *always* get here!\n"; } ); # # The above was a more compact way of doing this: # my $quoted = OP::Array->new(); for ( @{ $array } ) { print "Have item: $_\n"; next if $_ =~ /donotwant/; $quoted->push( $myClass->quote($_) ); print "You will *always* get here!\n"; }
The indexed version of
collect
iscollectWithIndex
. It provides the index integer as a second argument to the received CODE block.my $new = $array->collectWithIndex( sub { my $item = shift; my $index = shift; print "Working on item $index: $item\n"; } );
$array->each($sub)
$array->eachWithIndex($sub)
return, break
List iterator method. Runs $sub for each element in self; returns true on success.
Just as in
collect
,return
skips to the next iteration, andbreak
breaks the loop. Array elements are accessed in the same manner ascollect
.my $arr = OP::Array->new( qw| foo bar rebar | ); $arr->each( sub { my $item = shift; print "Have item: $item\n"; } ); # # Expected output: # # Have item: foo # Have item: bar # Have item: rebar #
The indexed version of
each
iseachWithIndex
. It provides the index integer as a second argument to the received CODE block.$array->eachWithIndex( sub { my $item = shift; my $index = shift; print "Have item $index: $item\n"; } ); # # Expected output: # # Have item 0: foo # Have item 1: bar # Have item 2: rebar #
$array->join($joinStr)
Object wrapper for Perl's built-in
join()
function. Functionally the same asjoin($joinStr, @{ $self })
.my $array = OP::Array->new( qw| foo bar | ); my $string = $array->join(','); # returns "foo,bar"
$array->compact()
Removes any undefined elements from self.
my $array = OP::Array->new( 'foo', undef, 'bar' ); $array->compact(); # Array becomes ('foo', 'bar')
$array->unshift()
Object wrapper for Perl's built-in
unshift()
function. Functionally the same asunshift(@{ $self })
.my $array = OP::Array->new('bar'); $array->unshift('foo'); # Array becomes ('foo', 'bar')
$array->rand()
Returns a pseudo-random array element.
my $array = OP::Array->new( qw| heads tails | ); my $flip = $array->rand(); # Returns 'heads' or 'tails' randomly
$array->isEmpty()
Returns a true value if self contains no values, otherwise false.
my $array = OP::Array->new(); if ( $array->isEmpty() ) { print "Foo\n"; } $array->push('anything'); if ( $array->isEmpty() ) { print "Bar\n"; } # # Expected Output: # # Foo #
$array->includes($value)
Returns a true value if self includes the received value, otherwise false.
my $array = OP::Array->new( qw| foo bar | ); for my $key ( qw| foo bar rebar | ) { next if $array->includes($key); print "$key does not belong here.\n"; } # # Expected output: # # rebar does not belong here. #
$array->grep($expr, [$mod])
Returns an array of scalar matches if the expression has any hits in the array. Wrapper for Perl's built-in
grep()
function.The second argument is an optional regex modifier string (e.g. "i", "gs", "gse", etc).
my $array = OP::Array->new( qw| Jimbo Jimbob chucky | ); for ( @{ $array->grep(qr/^jim/, "i") } ) { print "Matched $_\n"; }; # # Expected output: # # Matched Jimbo # Matched Jimbob #
$array->clear()
Removes all items, leaving self with zero array elements.
my $array = OP::Array->new( qw| foo bar | ); my $two = $array->size(); # 2 $array->clear(); my $zero = $array->size(); # 0
$array->purge()
Explicitly purges each item in self, leaving self with zero array elements.
Useful in cases of arrays of CODE references, which are not otherwise cleaned up by Perl's GC.
$array->average()
Returns the average of all items in self.
my $arr = OP::Array->new( qw| 54343 645564 89890 32 342 564564 | ); my $average = $arr->average(); print "Avg: $average\n"; # Avg: 225789.166666667
$array->median()
Returns the median value of all items in self.
my $arr = OP::Array->new( qw| 54343 645564 89890 32 342 564564 | ); my $median = $arr->median(); print "Med: $median\n"; # Med: 89890
$array->max()
Returns the highest value of all items in self.
my $arr = OP::Array->new( qw| 54343 645564 89890 32 342 564564 | ); my $max = $arr->max(); print "Max: $max\n"; # Max: 645564
$array->min()
Returns the lowest value of all items in self.
my $arr = OP::Array->new( qw| 54343 645564 89890 32 342 564564 | ); my $min = $arr->min(); print "Min: $min\n"; # Min: 32
$array->sum()
Returns the sum of all items in self.
my $arr = OP::Array->new( qw| 54343 645564 89890 32 342 564564 | ); my $sum = $arr->sum(); print "Sum: $sum\n"; # Sum: 1354735
$array->stddev()
Return the standard deviation of the current set.
my $array = OP::Array->new(2, 4, 4, 4, 5, 5, 7, 9); my $stddev = $array->stddev; # 2
$array->sort([$function])
Wrapper to Perl's built-in
sort
function.Accepts an optional argument, a sort function to be used. Sort function should take $a and $b as arguments.
my $alphaSort = $array->sort(); my $numSort = $array->sort(sub{ shift() <=> shift() });
$array->first()
Returns the first item in the array. Same as $array->[0].
my $array = OP::Array->new( qw| alpha larry omega | ); print $array->first(); print "\n"; # Prints "alpha\n"
$array->last()
Returns the final item in the array. Same as $array->[-1].
my $array = OP::Array->new( qw| alpha larry omega | ); print $array->last(); print "\n"; # Prints "omega\n"
$array->uniq();
Returns a copy of self with duplicate elements removed.
$array->reversed();
Returns a copy of self with elements in reverse order
$array->pop()
Object wrapper for Perl's built-in
pop()
function. Functionally the same aspop(@{ $self })
.my $array = OP::Array->new( qw| foo bar rebar | ); while ( my $element = $array->pop() ) { print "Popped $element\n"; } if ( $array->isEmpty() ) { print "Now it's empty!\n"; } # # Expected output (note reversed order): # # Popped rebar # Popped bar # Popped foo # Now it's empty! #
$array->shift()
Object wrapper for Perl's built-in
shift()
function. Functionally the same asshift(@{ $self })
.my $array = OP::Array->new( qw| foo bar | ); while( my $element = $array->shift() ) { print "Shifted $element\n"; } if ( $array->isEmpty() ) { print "Now it's empty!\n"; } # # Expected output: # # Shifted foo # Shifted bar # Now it's empty! #
SEE ALSO
This file is part of OP.