atcroft has asked for the wisdom of the Perl Monks concerning the following question:
To the members of the body monktorate, greetings.
I seek your wisdom. I am trying to teach myself to use Moose (or the associated variations, such as Mouse, Moo, Mo, etc.). For my learning project, I wanted to do something I felt more useful than the Animal example, so for my purposes I wanted to represent a particle. I created a StationaryParticle, then extended it to a MoveableParticle. Because I want it to move within a limited rectangular space, I began trying to add a Boundary object to the system, which I added as a singleton for now (because in most cases particles would have the same boundaries). This is when I came to my problem.
In my way of thinking I would either group a boundary based on aggregation (min/max) then dimension (x/y), or vice versa, so I might define either of the following:
(For the remainder of the code, I will go with the aggregation-first model, although the issue occurs either way.)my $boundary_aggregation_first = ( min => { x => 0, y => 0, }, max => { x => 639, y => 479, }, ); my $boundary_dimension_first = ( x => { min => 0, max => 639, }, y => { min => 0, max => 479, }, );
When I try to code that into Moo (or Moose), I'm not sure how best to handle that object. I would think I should be able to add the limit through a method, but I cannot seem to reason out what that method should look like. If I break encapsulation I could it could be as easy as $wall->limit->{min}{x} = 0, but I don't want to be *that guy* who tromps through code (and for whom it blows up if the Boundary objects change later.)
package Boundary; use strictures 2; use namespace::clean; use Data::Dumper; use Moo; use MooX::Types::MooseLike::Base qw/ HashRef Int Maybe /; with q{MooX::Singleton}; has q{limit} => ( is => q{rw}, isa => HashRef [ HashRef [ Maybe [Int] ] ], traits => [ q{Hash}, ], default => sub { {} }, );
I then tried a 'before' call to try to allow me to hand it a HoH and set the values there, or pass in a HoH with an undefined value to hopefully return the value:
before q{limit} => sub { my $self = shift; if ( scalar @_ ) { my $val = shift; if ( ref $val eq q{HASH} ) { foreach my $k ( keys %{$val} ) { if ( defined $val->{$k}->{$l} ) { $self->limit->{$k}{$l} = $val->{$k}->{$l}; } else { my $result = $self->limit->{$k}{$l}; return $result; } } } } }; __PACKAGE__->meta->make_immutable; 1; package main; my $wall = Boundary->instance(); $wall->limit( { min => { x => 0, y => 0, }, max => { x => 639, y => 478, }, }, ); # ... say $wall->limit( { min => { x => undef, }, }, ); # Expected: 0 # Actual: HASH(0x801a440b8) say $wall->limit( { max => { x => undef, }, }, ); # Expected: 639 # Actual: HASH(0x801a44160)
What I see with this is that I appear to be replacing the singleton when I try to use the undef setting to retrieve the value.
What is the proper way to do what I am trying to accomplish?
Thank you for your time and attention, and any guidance/assistance you may provide. Have a great day, and stay safe!
sscce.pl:
use strict; use warnings; use 5.014; use Moo; use strictures 2; use namespace::clean; package Boundary; use Data::Dumper; use Moo; use MooX::Types::MooseLike::Base qw/ HashRef Int Maybe /; with q{MooX::Singleton}; has 'limit' => ( is => q{rw}, isa => HashRef [ HashRef [ Maybe [Int] ] ], traits => [ q{Hash}, ], default => sub { {} }, ); before q{limit} => sub { my $self = shift; if ( scalar @_ == 1 ) { my $val = shift; if ( ref $val eq q{HASH} ) { foreach my $k ( keys %{$val} ) { foreach my $l ( keys %{ $val->{$k} } ) { if ( defined $val->{$k}->{$l} ) { $self->limit->{$k}{$l} = $val->{$k}->{$l}; } else { my $result = $self->limit->{$k}{$l}; return $result; } } } } } }; __PACKAGE__->meta->make_immutable; 1; package main; # use Boundary; my $wall = Boundary->instance(); $wall->limit( { min => { x => 0, y => 0, }, max => { x => 320, y => 240, }, }, ); say $wall->limit->{min}{x}; say $wall->limit->{min}{y}; say $wall->limit->{max}{x}; say $wall->limit->{max}{y}; # $wall->limit->{max}{x} = 325; # $wall->limit->{max}{y} = 245; say __LINE__ . q{: }, $wall->limit( { max => { x => 325, y => 245, }, }, ); say __LINE__ . q{: }, $wall->limit( { max => { q{x} => undef, }, }, ); say __LINE__ . q{: }, $wall->limit( { max => { q{y} => undef, }, }, ); # $wall->limit->{max}{x} = 320; # $wall->limit->{max}{y} = 240; $wall->limit( { max => { x => 320, y => 240, }, }, ); __END__
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Question regarding proper handling of a Hash/HashRef structure in Moose-variants
by haj (Vicar) on Dec 22, 2021 at 08:22 UTC | |
by NERDVANA (Priest) on Dec 22, 2021 at 20:46 UTC | |
Re: Question regarding proper handling of a Hash/HashRef structure in Moose-variants
by bliako (Abbot) on Dec 23, 2021 at 08:30 UTC |