{
package Row;
use Moose;
use Moose::Util::TypeConstraints;
has 'row' => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[Cell]',
required => 1,
default => sub { [] },
handles => {
pushCell => 'push',
getCell => 'get',
allCells => 'elements',
},
);
}
####
sub addCell {
my ($self, $index, @cells) = @_;
$self->pushRow( [] ) if !defined $self->getRow($index);
$self->getRow($index)->pushCell(@cells);
}
####
{
package Grid;;
use Moose;
use Moose::Util::TypeConstraints;
# coerce an 'ArrayRef[ArrayRef[Cell]]' struct provided by the caller into an 'ArrayRef[Row]' type
subtype 'A::Row' => as 'ArrayRef[Row]';
coerce 'A::Row' => from 'ArrayRef[ArrayRef[Cell]]' => via { [ map {Row->new( row => $_ )} @$_ ] };
# coerce an 'ArrayRef[Cell]' struct provided by the caller into a 'Row' type
coerce 'Row' => from 'ArrayRef[Cell]' => via { Row->new( row => $_ ) };
has 'grid' => (
traits => ['Array'],
is => 'ro',
isa => 'A::Row',
required => 1,
default => sub { [] },
coerce => 1,
handles => {
addRow => 'push',
getRow => 'get',
allRows => 'elements',
},
);
}
####
my $grid = Grid->new( grid => [
[$cellA0, $cellB0, $cellC0],
[$cellA1, $cellB1, $cellC1],
[$cellA2],
] );
####
#!/usr/bin/perl -w
use Modern::Perl '2011';
{
package Cell;
use Moose;
has 'name' => (
is => 'rw',
isa => 'Str',
default => '',
);
no Moose;
__PACKAGE__->meta->make_immutable;
}
{
package Row;
use Moose;
use Moose::Util::TypeConstraints;
has 'row' => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[Cell]',
required => 1,
default => sub { [] },
handles => {
pushCell => 'push',
getCell => 'get',
allCells => 'elements',
},
);
sub toString {
my $self = shift;
join "\t", map($_->name, $self->allCells);
}
no Moose;
no Moose::Util::TypeConstraints;
__PACKAGE__->meta->make_immutable;
}
{
package Grid;;
use Moose;
use Moose::Util::TypeConstraints;
# coerce an 'ArrayRef[ArrayRef[Cell]]' struct provided by the caller into an 'ArrayRef[Row]' type
subtype 'A::Row' => as 'ArrayRef[Row]';
coerce 'A::Row' => from 'ArrayRef[ArrayRef[Cell]]' => via { [ map {Row->new( row => $_ )} @$_ ] };
# coerce an 'ArrayRef[Cell]' struct provided by the caller into a 'Row' type
coerce 'Row' => from 'ArrayRef[Cell]' => via { Row->new( row => $_ ) };
has 'grid' => (
traits => ['Array'],
is => 'ro',
isa => 'A::Row',
required => 1,
default => sub { [] },
coerce => 1,
handles => {
addRow => 'push',
getRow => 'get',
allRows => 'elements',
},
);
sub addCell {
my ($self, $index, @cells) = @_;
$self->addRow( [] ) if !defined $self->getRow($index);
$self->getRow($index)->pushCell(@cells);
}
sub toString {
my $self = shift;
join "\n", map {join "\t", map($_->name, $_->allCells)} $self->allRows;
}
no Moose;
no Moose::Util::TypeConstraints;
__PACKAGE__->meta->make_immutable;
}
use strict;
##################
### Test Cases ###
##################
# testing Row class
#CASE #1: create a new instance by first building a row (reference to an array), and then passing this to the constructor
print "BEGIN row1 test\n";
my $row;
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "${y}0" );
push @$row, $mycell;
}
my $row1 = Row->new( row => $row );
print $row1->toString . "\n";
my $mycell = Cell->new( name => "F0" );
$row1->pushCell($mycell);
print $row1->toString . "\n";
#$row1->pushCell( q/Whammi/ );
#print $row1->toString . "\n";
print "END row1 test\n\n";
#CASE #2: create a new empty instance of a row, then add new elements individually.
print "BEGIN row2 test\n";
my $row2 = Row->new;
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "${y}0" );
$row2->pushCell($mycell);
}
print $row2->toString . "\n";
#$row2->pushCell( q/Whammi/ );
#print $row2->toString . "\n";
print "END row2 test\n\n";
# testing Grid class
#CASE #1A: create a new Grid instance by first building an array of Row structs, and then passing this to the constructor (as a reference)
print "BEGIN grid1A test\n";
my $struct1A;
#my @struct1A; # both of these methods work
for my $x (0 .. 4) {
my $rowRef;
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "$y$x" );
push @$rowRef, $mycell;
}
my $row = Row->new( row => $rowRef );
push @$struct1A, $row;
#push @struct1A, $row;
}
my $grid1A = Grid->new( grid => $struct1A );
#my $grid1A = Grid->new( grid => \@struct1A );
print $grid1A->toString . "\n";
print "\n";
my $mycell1A = Cell->new( name => "F3" );
$grid1A->addCell(3, $mycell1A);
print $grid1A->toString . "\n";
#$grid1A->addCell(3, q/Whammi/);
#print $grid1A->toString . "\n";
print "END grid1A test\n\n";
#CASE #1B: create a new Grid instance by first building a 2d-array of Cell structs, and then passing this to the constructor (as a reference) :: coercion needs to be working for this to succeed
print "BEGIN grid1B test\n";
#my $struct1B;
my @struct1B; #both methods work
for my $x (0 .. 4) {
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "$y$x" );
#push @{$$struct1B[$x]}, $mycell; # yikes! that's pretty scary! Builds an array-of-arrays-of-Cells as a reference
push @{$struct1B[$x]}, $mycell;
}
}
#my $grid1B = Grid->new( grid => $struct1B );
my $grid1B = Grid->new( grid => \@struct1B );
print $grid1B->toString . "\n";
print "\n";
my $mycell1B = Cell->new( name => "F3" );
$grid1B->addCell(3, $mycell1B);
print $grid1B->toString . "\n";
#$grid1B->addCell(3, q/Whammi/);
#print $grid1B->toString . "\n";
print "END grid1B test\n\n";
#CASE #2A: create a new empty Grid instance, then add new rows individually as Row structs.
print "BEGIN grid2A test\n";
my $grid2A = Grid->new;
for my $x (0 .. 4) {
#my $rowRef;
my @row; # both of these methods work as well
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "$y$x" );
#push @$rowRef, $mycell;
push @row, $mycell;
}
#my $row = Row->new( row => $rowRef );
my $row = Row->new( row => \@row );
$grid2A->addRow( $row );
}
print $grid2A->toString . "\n";
print "\n";
my $mycell2A = Cell->new( name => "F3" );
$grid2A->addCell(3, $mycell2A);
print $grid2A->toString . "\n";
#$grid2A->addCell(3, q/Whammi/);
#print $grid2A->toString . "\n";
print "END grid2A test\n\n";
#CASE #2B: create a new empty Grid instance, then add new rows individually as an array of Cell structs :: coercion needs to be working for this to succeed
print "BEGIN grid2B test\n";
my $grid2B = Grid->new;
for my $x (0 .. 4) {
#my $rowRef;
my @row; # both of these methods work
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "$y$x" );
#push @$rowRef, $mycell;
push @row, $mycell;
}
$grid2B->addRow( \@row );
#$grid2B->addRow( $rowRef );
}
print $grid2B->toString . "\n";
print "\n";
my $mycell2B = Cell->new( name => "F3" );
$grid2B->addCell(3, $mycell2B);
print $grid2B->toString . "\n";
#$grid2B->addCell(3, q/Whammi/);
#print $grid2B->toString . "\n";
print "END grid2B test\n\n";
#CASE #3: create a new empty Grid instance, then add new rows individually as an array of Cell structs :: coercion needs to be working for this to succeed
#this differs from CASE 2B in that I am constructing an anonymous array in one expression, rather than pushing the elements one-by-one onto the anon array.
print "BEGIN grid3 test\n";
my $grid3 = Grid->new;
my $o1 = Cell->new( name => 'X1' );
my $o2 = Cell->new( name => 'Y1' );
my $o3 = Cell->new( name => 'Z1' );
$grid3->addRow([$o1, $o2, $o3]);
print $grid3->toString . "\n";
my $o4 = Cell->new( name => 'W1' );
$grid3->addCell(0, $o4);
print $grid3->toString . "\n";
#$grid3->addRow( qw/Whammi1 Whammi2/ );
#print $grid3->toString . "\n";
print "END grid3 test\n\n";
#CASE #4: last case; create a new empty Grid instance, then add each cell one-by-one
print "BEGIN grid4 test\n";
my $grid4 = Grid->new;
for my $x (0 .. 4) {
for my $y ("A" .. "E") {
my $mycell = Cell->new( name => "$y$x" );
$grid4->addCell($x, $mycell);
}
}
print $grid4->toString . "\n";
print "\n";
my $mycell4A = Cell->new( name => "F3" );
$grid4->addCell(3, $mycell4A);
print $grid4->toString . "\n";
print "\n";
my $mycell4B = Cell->new( name => "A5" );
$grid4->addCell(5, $mycell4B);
print $grid4->toString . "\n";
print "END grid4 test\n\n";
####
BEGIN row1 test
A0 B0 C0 D0 E0
A0 B0 C0 D0 E0 F0
END row1 test
BEGIN row2 test
A0 B0 C0 D0 E0
END row2 test
BEGIN grid1A test
A0 B0 C0 D0 E0
A1 B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3 F3
A4 B4 C4 D4 E4
END grid1A test
BEGIN grid1B test
A0 B0 C0 D0 E0
A1 B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3 F3
A4 B4 C4 D4 E4
END grid1B test
BEGIN grid2A test
A0 B0 C0 D0 E0
A1 B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3 F3
A4 B4 C4 D4 E4
END grid2A test
BEGIN grid2B test
A0 B0 C0 D0 E0
A1 B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3 F3
A4 B4 C4 D4 E4
END grid2B test
BEGIN grid3 test
X1 Y1 Z1
X1 Y1 Z1 W1
END grid3 test
BEGIN grid4 test
A0 B0 C0 D0 E0
A1 B1 C1 D1 E1
A2 B2 C2 D2 E2
A3 B3 C3 D3 E3 F3
A4 B4 C4 D4 E4
A5
END grid4 test