NAME
Devel::Ladybug::Array - Array object class
DESCRIPTION
Extends Devel::Ladybug::Object to handle Perl ARRAY refs as Devel::Ladybug 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:
Devel::Ladybug::Class > Devel::Ladybug::Object > Devel::Ladybug::Array
SYNOPSIS
use Devel::Ladybug::Array;
my $emptyList = Devel::Ladybug::Array->new();
my $arrayFromList = Devel::Ladybug::Array->new(@list); # Makes new ref
my $arrayFromRef = Devel::Ladybug::Array->new($ref); # Keeps orig ref
METHODS
Public Class Methods
$class->new(@list)
Instantiate a new Devel::Ladybug::Array. Accepts an optional array or array reference as a prototype object
Usage is cited in the SYNOPSIS section of this document.
$class->assert(Devel::Ladybug::Type $memberType, *@rules)
Return a new Devel::Ladybug::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 Devel::Ladybug qw| :all |; create "YourApp::Example" => { # # An array of strings: # someArr => Devel::Ladybug::Array->assert( Devel::Ladybug::Str->assert() ), ... };
In Caller:
#!/bin/env perl # # File: somecaller.pl # use strict; use warnings; use YourApp::Example; my $exa = YourApp::Example->spawn("Array Example"); $exa->setSomeArr("Foo", "Bar", "Rebar", "D-bar"); $exa->save();
Nested Arrays: At the cost of performance, array assertions may be nested. Each assert has independent rules:
# # File: Example.pm # use Devel::Ladybug qw| :all |; create "YourApp::Example" => { # # Fancy... a 3x3 matrix of integers with per-element enforcement of # min and max values: # matrix => Devel::Ladybug::Array->assert( Devel::Ladybug::Array->assert( Devel::Ladybug::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 YourApp::Example; my $example = YourApp::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::Array->new(); $array->push($something); $array->push( qw| foo bar | );
$array->count()
Object wrapper for Perl's built-in
scalar()
function. Functionally the same asscalar(@$ref)
.my $array = Devel::Ladybug::Array->new( qw| foo bar | ); my $count = $array->count(); # returns 2
$array->each($sub)
yield(item, [item, ...]), emit(item, [item, ...]), return, break
List iterator method.
each
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 Devel::Ladybug::Array instance.This Perl implementation of
each
is borrowed from Ruby's implementation ofcollect
andeach
.To finely control the flow of execution when iterating, several functions may be used. These are
yield
,emit
,break
, and Perl's ownreturn
. These are explained in greater detail in the Collector Control Flow section of this document.This collector pattern is used throughout Devel::Ladybug. The following pseudocode illustrates its possible usage.
my $array = Devel::Ladybug::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->each($sub);
A simple working example - return a new array containing capitalized versions of each element in the original.
my $array = Devel::Ladybug::Array->new( qw| foo bar baz whiskey tango foxtrot | ); my $capped = $array->each( 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
each
sub may be controlled usingreturn
,yield
,emit
, andbreak
.break
invokes Perl'slast
, breaking execution of theeach
loop.In the context of the
each
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 unlikereturn
, items passed as arguments toyield
are added to the end of the returned array.emit
adds items to the returned array, and then resumes execution of the sub in progress. Emitted items are added to the array returned by theeach
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
each
sub in an iteration, nothing will be added to the returned array for that item. To yield nothing for an iteration, don't useyield
. If you must, usereturn
instead to skip ahead to the next iteration, to avoid undefined elements in the returned array.If yielding multiple items at a time, they are added to the array returned by
each
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 theeach
sub, in addition to causing Perl to jump ahead to the next iteration, likenext
in afor
loop would.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->each( 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 = Devel::Ladybug::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 theeach
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.# # For example, create a new Array ($quoted) containing quoted elements # from the original, omitting items which aren't wanted. # my $quoted = $array->each( 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 = Devel::Ladybug::Array->new(); for ( @{ $array } ) { print "Have item: $_\n"; next if $_ =~ /donotwant/; $quoted->push( $myClass->quote($_) ); print "You will *always* get here!\n"; }
each
provides the index integer as a second argument to the received CODE block.my $new = $array->each( sub { my $item = shift; my $index = shift; print "Working on item $index: $item\n"; } );
$array->eachTuple($sub);
Shorthand iterator for multi-dimensional arrays.
# # $array looks like: # [ # [ "adam", "0" ], # [ "bob", "1" ], # [ "carl", "2" ], # [ "dave", "3" ], # ] # $array->eachTuple( sub { my $first = shift; my $second = shift; # ... } ); ### ### The above was shorthand for: ### # $array->each( sub { # my $row = shift; # my $first = $row->shift; # my $second = $row->shift; # ... # } );
$array->join($joinStr)
Object wrapper for Perl's built-in
join()
function. Functionally the same asjoin($joinStr, @{ $self })
.my $array = Devel::Ladybug::Array->new( qw| foo bar | ); my $string = $array->join(','); # returns "foo,bar"
$array->compact()
Removes any undefined elements from self.
my $array = Devel::Ladybug::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 = Devel::Ladybug::Array->new('bar'); $array->unshift('foo'); # Array becomes ('foo', 'bar')
$array->rand()
Returns a pseudo-random array element.
my $array = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::Array->new( qw| foo bar | ); my $two = $array->count(); # 2 $array->clear(); my $zero = $array->count(); # 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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 = Devel::Ladybug::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 Devel::Ladybug.