Perl Moose with Min, Max, and Default

Using Moose, you can create attributes with a default value. I have a set of attributes that have a minimum, maximum, and default value. These are attributes representing the scale (e.g. Tk :: Scale).

Currently, I have at least 3 attributes: current and default:

has 'attr' => (is => 'rw', isa => 'Int', default => 300, lazy => 1, clearer => '_clear_attr'); 

min:

 has 'attr_min' => (is => 'rw', isa => Int', default => 100); 

tach:

 has 'attr_max' => (is => 'rw', isa => Int', default => 1000); 

Is it possible to have all four (current, default, min, max) in one attribute?

+7
source share
2 answers

I think you want to create a validation rule.

 use Moose::Util::TypeConstraints; subtype 'ScaleVal', as 'Int', where { 100 <= $_ && $_ <= 1000 }; has attr => ( is => 'rw', isa => 'ScaleVal', default => 300, ); 
+7
source

Of course, there are many ways to combine a bunch of values ​​into a more complex value - mainly regarding the study of data structures. Which specific data structures to choose is a rather complicated question, highly dependent on your actual use cases.

I know quite a bit about your case, but what I learned from your question is that all these attributes are similarly structured concepts. And so I would create a new data type, Scale :

 use MooseX::Declare; class Scale { for (qw/min max def/) { has $_ => (is => 'ro', isa => 'Num', required => 1); } has val => (is => 'rw', isa => 'Num', lazy_build => 1); method _build_val() { return $self->def; } method BUILD($args) { confess "Out of range!" unless $self->_is_in_range($self->val); } method _is_in_range($val) { return defined $val && $val >= $self->min && $val <= $self->max; } before val ($new_val?) { return unless defined $new_val; confess "Out of range!" unless $self->_is_in_range($new_val); } } 

And I would introduce the attributes on some ThingWithScale that was supported by the Scale object.

 class ThingWithScale { has _attr => ( is => 'ro', isa => 'Scale', default => sub { shift->_make_attr() }, ); method _make_attr($class: $val?) { return Scale->new( min => 100, max => 1000, def => 200, (defined $val ? (val => $val) : ()), ) } # Convert `attr` argument to a `Scale` object before passing to real constructor. sub BUILDARGS { my ($class, %args) = @_; if (defined (my $attr = delete $args{attr})) { %args = ( %args, _attr => $class->_make_attr($attr) ); } return $class->SUPER::BUILDARGS(%args); } } my $thing = ThingWithScale->new(attr => 101); 

And around the time I was writing this BUILDARGS method to automatically instantiate a Scale object from a simple constructor parameter, I would understand that what I really wanted to do was invent a new trait attribute to describe the attributes with the minimum and maximum legal values.

+1
source

All Articles