The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

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.

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 as push(@$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 as scalar(@$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 of collect and each.

    To finely control the flow of execution when iterating, several functions may be used. These are yield, emit, break, and Perl's own return. 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 using return, yield, emit, and break.

    break invokes Perl's last, breaking execution of the each loop.

    In the context of the each sub, return is like Perl's next or Javascript's continue- 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, using return to reap yielded elements is not workable, so we use yield for this instead. Any arguments to return in this context are ignored.

    Like return, yield stops execution of the sub in progress, but unlike return, items passed as arguments to yield 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 the each sub, just like yield, but you may call emit 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 use yield. If you must, use return 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 the each sub, in addition to causing Perl to jump ahead to the next iteration, like next in a for 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 (ie next).

      #
      # 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 the each sub, but does so without returning (that is, execution of the sub in progress will continue uninterrupted). It's just like pushing to an array from inside a for 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 as join($joinStr, @{ $self }).

      my $array = Devel::Ladybug::Array->new( qw| foo bar | );
    
      my $string = $array->join(','); # returns "foo,bar"
  • $array->unshift()

    Object wrapper for Perl's built-in unshift() function. Functionally the same as unshift(@{ $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->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 as pop(@{ $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 as shift(@{ $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

perlfunc, Math::VecStat

This file is part of Devel::Ladybug.