3 posts tagged “moosex-types”
One thing which has come up from time to time on the Moose Type Constraint wish list is the ability to more easily define type parameters. For example, it would be great if we could very simple create an Integer type that is bound by a range. For example:
subtype Range,
as Dict[max=>Int, min=>Int],
where {
my $range = shift @_;
return $range->{max} > $range->{min};
};
subtype RangedInt,
as Dependent[Int, Range],
where {
my ($int,$range) = @_;
return ($int >= $range->{min} && $int <= $range->{max});
};
class MyClass {
has young_adult_age => ( is=>'ro', isa=>RangedInt[min=>18,max=>34] );
}
And you can instantiate this like so:
MyClass->new(young_adult_age=>20);
But the following will throw an exception:
MyClass->new(young_adult_age=>40);
This gives your Moose based Perl programming a bit more flexibility!
Right now this is not on CPAN, but you can see it, play with it (and help me shed light on any of the corner cases) at: https://jules.scsys.co.uk/gitweb/gitweb.cgi?p=gitmo/MooseX-Dependent.git;a=tree
At this point the code is shaping up, although there's a bit of ugly stuff in the type constraint code. Even coercions work as you might hope.
Pending responses to the above syntax, remaining things before CPAN is primarily some attribute traits so that we can expose $self to a dependent type in a class. This would allow something like:
class Person {
has people => (is=>'ro', isa=>PeopleResultSet, required=>1);
has id => (is=>'ro', is=>UniqueID[PeopleResultSet], traits=>['Dependent']);
}
The idea being that the attribute 'id' would be bound to the attribute 'people' so that you could not create a new Person that had a pre-existing ID. The attribute trait stuff is still pending and feedback, test cases / use cases and of course code are very welcome.
UPDATED: My apologies for rebranding the date to anyone who has a working aggregator, but seems that whatever the settings for the Ironman aggregator, it wasn't picking up my post. Maybe I'm supposed to say, "Perl Programming now..."
Since I last wrote have been working a lot improving the MooseX::Types library system and cleaning up some related issues in Moose, as well as developing the new MooseX::Types::Structured type constraint library. First off, MooseX::Types now properly supports parameterized types, so you can:
subtype ArrayRefOfInts,
as ArrayRef[Int];
and it will work as expected. Recursive types let's you create something like:
subtype Tree,
as ArrayRef[Branch];subtype Branch,
as ArrayRef[Branch|Leaf];
Which basically means "A Tree is an array reference of one or more Branch(es) and each Branch is an array reference to more Branch(es) or Leaves". Notice the '|' overloading to support the Union 'Or' type constraint.
I know this is just a taste, more details to come later. Until then you'll have to make do with the linked documentation and associated test examples.
Happy New Year!
MooseX::Types is an alternative method for creating an managing your Moose type constraints. This has been recently updated to properly support parameterized type constraints and type constrain unions. So now you can correctly do:
subtype MyArrayRefOfIntegers,
as ArrayRef[Int];
subtype BigInt,
as Int,
where { $_ >10 };
subtype MyArrayRefOfBigInts,
as MyArrayRefOfIntegers[BigInt];
So there are a few things going on here. First of all “MyArrayRefOfIntegers” is defined as a parameterized ArrayRef and will match [1,2,3, ...] but not ['a','b','c', …] since that data structure contains strings. We also created a subtype called “BigInt” which is an integer with a further requirement that the value be greater than 10. Granted, you may not consider this very big, but it will serve for example. Then, we define another type constraint which is a subtype of the previously created parameterized type. We call this one, “MyArrayRefOfBigInts”, since it extends the “MyArrayRefOfIntegers” subtype with a new type parameter, the previously created “BigInt”. This will match [11,12,13, ...], but not [1,2,3, …], since the latter violates the “BigInt” constraint. This ability for a parameterized type subtype it's type parameter is a recent addition to Moose, so you'll need at least the 0.60 version.
If you extend a parameterized subtype this way, the new type parameter must be a subtype of the type parameter of the parent type. So this could be any subtype of “Int” but not “Str”. If you try, you'll get an error.
Please note you could have done the following to achieve the same effect:
subtype MyArrayRefOfBigInts,
as MyArrayRefOfIntegers,
where { foreach my $int (@$_) {$int > 10 || return 0} 1 };
However, I believe the first example is cleaner and offers additional reusability.
Type constraint unions are straightforward:
subtype MyThisOrThat,
as Int|Str;
This would match either an Int or a Str type constraint. Personally, I don't use these type of constraints very much since I suspect they may indicate improper abstraction at some level, but to each her own. Of course can can mix and match:
subtype MyBigMess,
as HashRef[HashRef[Num|Object]|ArrayRef[Str|Object]];
However at some point you need to start wondering if what you are doing is sane :)
If you are using MooseX::Types in your applications, please update to the latest and let me know if you find any problems.