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   ____----____----

Reply via email to