Hello Moose Team et al,
I'm looking for moose documentation, example code or missing key concepts
to handle a hash of hash of array of objects. See 2 sample files:
HrArObj.pl and Farm.pm
Questions are noted by XXX_question_
__--__--__ File HrArObj.pl __--__--__
#!/usr/bin/env perl -l
use lib qw( /var/tmp/pbuild/lib/perl5 /Users/dcb/dvlp/lib);
use Moose;
use Moose::Util::TypeConstraints;
use Declare::Constraints::Simple -All;
use Farm;
{
package Animal;
use Moose;
use Moose::Util::TypeConstraints;
## ToDo: write tests about Legs
##
subtype 'Legs'
=> as 'Int'
=> where { length $_ > 0 } ##
=> message { "$_ Legs: 0 - 4 "};
has 'name' => (is => 'rw');
has 'color' => (is => 'rw', default => sub { shift->default_color});
## requires 'default_color';
has 'pedal' => (is => 'rw', isa => 'Legs');
sub speak {
my $self = shift;
print $self->name, " goes ", $self->sound, "\n";
}
}
{
package Domesticated;
use Moose::Role;
has 'is_friendly' => (
is => 'rw',
isa => 'Bool',
);
sub wild {
my $self = shift;
print "Wild Spirits\n";
$self->is_friendly(1);
};
}
{
package Horse;
use Moose;
extends 'Animal'; ## inherit
with 'Domesticated'; ## role
use vars qw($VERSION);
use version; our $VERSION = qv(1.0611); # $MyPackage::VERSION = 1.061;
sub default_color { return 'brown' }
sub sound { return 'neigh'}
}
sub horse {
my $nelly = Horse->new( name => 'nell');
dbg " blessed horse " if Scalar::Util::blessed ($nelly); # Carp::confess
$nelly->sound;
$nelly->speak;
return $nelly;
}
# sub main {
my $farm = Farm->new( farmers_name => 'joe', name => 'in_the_Dell' );
my $talking_horse = Horse->new(name => 'Mr. Ed', color => 'grey');
my $horsey = Horse->new( name => 'shore', color => 'white' );
my $hor = Horse->new( name => 'hor', color => 'black' );
$farm->add_animal( $talking_horse ); # Add a few horses to the
$farm->add_animal( $horsey ); # livestock array.
$farm->add_animal( $hor );
$farm->addem( $horsey, ref $horsey, $horsey ); # Confusing!!!
# How do you insert into a hash of hashes of array of Animals?
$farm->partition( $horsey, ref $horsey, $horsey);
# Insert a new key/value pair into the horse into a hash.
$farm->corridor( $hor, ref $hor, $hor );
# Additional attempt to insert a hash of hashes of array of objects.
print " animal count: ", $farm->num_animals();
print "Horse bins_HrAn contents: ", $farm->corl(); # XXX_question_1
# How do you get the contents of
# the hash?
# It seems like get should
# retrieve the information.
my %crops = ( 'corn', 2,
'nuts', 6,
'olives', 8,
'wheat', 3);
my ( $crop, $acres);
while( ( $crop, $acres) = each %crops) { ## Farmer diversifies
$farm->setter( $crop => $acres ); ## by planting crops.
dbg "crop: $crop, acres: $acres ";
}
use Data::Dumper;
$Data::Dumper::Varname = 'farm'; #'Farm:_in_the_Dell';
dbg $farm->dump;
print "Ending program";
____----____----____ End of File HrArObj.pl ____----____----
____----____---- File Farm.pm ____----____----
package Farm;
use Moose;
use Moose::Util::TypeConstraints; # for types
use Test::Exception;
use Declare::Constraints::Simple -All; ## complaining!!!
##use Moose::Meta::Attribute::Native::MethodProvider::Hash;
# use Moose::Manual::MethodModifiers
use ldcb;
use lib qw( /var/tmp/pbuild/lib/perl5);
our ($VERSION) = '1.12.34.45';
## t/200_examples/004_example_w_DCS.t
##
has 'name' => (is => 'rw', isa => 'Str');
has 'farmers_name' => (is => 'rw', isa => 'Str');
my $ArrayRefAnimals = subtype 'ArrayRefAnimals',
as 'ArrayRef[Animal]';
my $HashRefArray = subtype 'HashRefArray',
as 'HashRef[ArrayRef]';
my $HoAoAnmls = subtype 'HoAoAnmls',
as 'HashRefArray[ArrayRefAnimals]'; ## The type we want
## to use.
##
# Hash of animals where the key is the animal name
# and the value is the animal object.
#
#
has 'yard' => (
traits => ['Hash'], ## trait: a role that applies to an
isa => 'HashRef[Animal]',
is => 'rw',
default => sub { {} },
handles => {
partition => [ set => ( 'previous') ], # XXX_question_2
# sub { if( ! exists($k) {
# [ set( $k, $v ]
#}
# }
## How do you insert a new key/value pair
## without overwriting the previous hash?
## The method partition should insert the new
## key/value of the new animal name (key) and
## value (animal object).
##
## This is coming from a place of ignorance --
## The symbol 'previous' from above is
## a placeholder for the set action.
## I'm not sure how to access the hash
## in order to insert the new k/v pair.
# partition => accessor( 'previous', 'bar') , # 'accessor'
corral => [ get => ('murky')], # 'get_bins'
},
);
before 'partition' => sub {
my ($self0,$self1,$self2,$self3) = @_; # Farm, object, type, name_key
if( keys(%{$self1}) ) {
print "type $self2 is in $self0 keys _exist_ in $self2 __--__ $self1 ";
print " ";
}
else {
print $self1, " is not defined";
}
};
after 'partition' => sub {
my ($slf0, $slf1, $slf2, $slf3) = @_;
if( keys(%{$slf0}) ) {
print "type $slf2 has keys ", scalar keys(%{$slf0});
}
};
##
# This data structure from the inside out is:
# Array of animal_objects in an animal type hash in a category hash.
#
# e.g $farm->animal_bins->Horse->[]
#
has 'animal_bins' => (
traits => ['Hash'], ## trait: a role that applies to an
isa => 'HashRef[Animal]',
# isa => 'HashRefArray[ArrayRefAnimals]', # XXX_question_3
## How can I make this type work with
## the animal_bins attribute?
## Is this the correct type for the
## task I want to perform?
## This type should be used instead of
## the type HashRef[Animal]
is => 'rw',
default => sub { { } },
## XXX_question_4
## If we consider pushing a new horse
## object:
## Method addem should push the horse object
## onto the array which is in the horse
## hash underneath the animal_bins hash.
##
## How can I do this?
##
## $farm->animal_bins->Horse->[]
handles => { ##
addem => ['set' => [push => sub { { $_[0] => [ $_[1] ] } }]],
corl => [ get => ('SeaHorse')], # This is an attempt to
corridor => ( [ set => 'Bullwinkle']), # get something working.
},
);
before 'addem' => sub { print " ..xxXX Inside before for animal_bins XXxx..";
};
after 'addem' => sub { print "\n XXxx.. AFTER animal_bins ..xxXX ";
};
around 'addem' => sub {
my $orig = shift; # accessor function ref
my $self = shift; # object
my $key = shift; # key
my @args = @_; # value(s)
my $retval = $self->$orig($key, @args) if @args; # use it
$retval ||= []; # if undefined, then create a blank arrayref
print " orig: $orig \t self: $self \t key: $key \t args: ", @args;
print " XX__XX retval: $retval";
print " args size: ", scalar @args;
printf(" arg1: %s arg2: %s ", $args[0], $args[1]);
return $retval;
};
##
# Array of animal objects.
#
#
has 'livestock' => (
traits => ['Array'], # native delegation
isa => 'ArrayRef[Animal]',
is => 'rw',
default => sub { [] },
handles => { ## built in delegation support.
add_animal => 'push',
num_animals => 'count',
n_of_em => 'natatime',
add_many_animals => 'splice',
}
);
subtype 'cultivated_crops'
=> as 'Str'
=> where { /^(corn|nuts|olives|wheat)/i }
=> message { "$_ is not valid!" };
coerce 'Int'
=> from 'cultivated_crops';
has 'crop_acres' => (
is => 'rw',
isa => 'HashRef[Int]',
traits => ['Hash'],
default => sub { {} },
handles => {
setter => 'set',
getter => 'get',
pairs => 'kv',
none => 'is_empty',
num_choices => 'count',
delete_choice => 'delete',
}
);
##
# Animals are first pushed on to the livestock array.
# Afterwards animals should be inserted into the
# yard hash. key: name value: Animal_object
#
after 'add_animal' => sub {
my ($self1, $self2) = @_;
## XXX_question_5
## How can I call partition from this attribute
## group to run a method from another attribute?
##
## add_animal is in the livestock attribute.
##
## partition is in the yard attribute.
##
## A call to partition should add the
## animal to the yard hash after it's been pushed on
## to the livestock array.
# $self1->partition( ref $self2, [$self2] );
# partition( $self1, ref $self2, $self2 );
};
sub number_of_animals {
my ($self) = @_;
my $number_of_animals = scalar $self->yard; # @yard; # $self->yard;
return $number_of_animals;
}
1;
____----____---- End of file Farm.pm ____----____----