+0.06 Fri Aug 5 12:00:00 EST 2008
+ - Added support for parameterized types and type unions, tests for all
+ that and documentation updates.
+
0.05 ...
- moved export mechanism to Sub::Exporter. ::Base contains
a bunch of wrapping logic to allow the export-along functionality
use namespace::clean -except => [qw( meta )];
-our $VERSION = 0.05;
+our $VERSION = 0.06;
my $UndefMsg = q{Action for type '%s' not yet defined in library '%s'};
# predeclare our own types
use MooseX::Types
- -declare => [qw( PositiveInt NegativeInt )];
+ -declare => [qw(
+ PositiveInt NegativeInt
+ ArrayRefOfPositiveInt ArrayRefOfAtLeastThreeNegativeInts
+ LotsOfInnerConstraints StrOrArrayRef
+ )];
# import builtin types
use MooseX::Types::Moose 'Int';
from Int,
via { 1 };
+ # with parameterized constraints. Please note the containing '(...)'
+
+ subtype ArrayRefOfPositiveInt,
+ as (ArrayRef[PositiveInt]);
+
+ subtype ArrayRefOfAtLeastThreeNegativeInts,
+ as (ArrayRef[NegativeInt]),
+ where { scalar(@$_) > 2 };
+
+ subtype LotsOfInnerConstraints,
+ as (ArrayRef[ArrayRef[HashRef[Int]]]);
+
+ # with TypeConstraint Unions
+
+ subtype StrOrArrayRef,
+ as Str|ArrayRef;
+
1;
=head2 Usage
=back
+=head1 NOTES REGARDING PARAMETERIZED CONSTRAINTS
+
+L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
+which generally allows you to easily create types with parameters such as:
+
+ subtype ParameterType,
+ as (ArrayRef[Int]);
+
+However, due to an outstanding issue you will need to wrap the parameterized
+type inside parenthesis, as in the example above. Hopefully this limitation
+will be lifted in a future version of this module.
+
+If you are using paramterized types in the options section of an attribute
+declaration, the parenthesis are not needed:
+
+ use Moose;
+ use MooseX::Types::Moose qw(HashRef Int);
+
+ has 'attr' => (isa=>HashRef[Str]);
+
+=head1 NOTES REGARDING TYPE UNIONS
+
+L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
+which generally allows you to easily create union types:
+
+ subtype StrOrArrayRef,
+ as Str|ArrayRef;
+
+As with parameterized constrains, this overloading extends to modules using the
+types you define in a type library.
+
+ use Moose;
+ use MooseX::Types::Moose qw(HashRef Int);
+
+ has 'attr' => (isa=>HashRef|Int);
+
+And everything should just work as you'd think.
+
=head1 METHODS
=head2 import
}
$type_constraint = defined($type_constraint) ? $type_constraint
: MooseX::Types::UndefinedType->new($name);
+
+ return $class->create_type_decorator($type_constraint);
- return $class->create_type_decorator($type_constraint);
+ #if(@_ && wantarray) {
+ # return ($class->create_type_decorator($type_constraint), @_);
+ #} else {
+ # return $class->create_type_decorator($type_constraint);
+ #}
};
}
my ($class, $name, @args) = @_;
### This whole section is a real TODO :) Ugly hack to get the base tests working.
my $fullname = $name."[$args[0]]";
+
+ #use Data::Dump qw/dump/;
+ #my $tc = Moose::Util::TypeConstraints::find_or_create_type_constraint($name);
+
return Moose::Util::TypeConstraints::create_parameterized_type_constraint($fullname);
}
sub create_type_decorator {
my ($class, $type_constraint) = @_;
- return MooseX::Types::TypeDecorator->new(type_constraint=>$type_constraint);
+ return MooseX::Types::TypeDecorator->new($type_constraint);
}
=head2 coercion_export_generator
Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
the C<#moose> cabal on C<irc.perl.org>.
+Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
+
=head1 LICENSE
This program is free software; you can redistribute it and/or modify
use warnings;
use Carp::Clan qw( ^MooseX::Types );
-use Moose::Util::TypeConstraints;
+use Moose::Util::TypeConstraints ();
use Moose::Meta::TypeConstraint::Union;
use overload(
'""' => sub {
- shift->type_constraint->name;
+ shift->__type_constraint->name;
},
'|' => sub {
my @tc = grep {ref $_} @_;
=cut
sub new {
- my ($class, %args) = @_;
- if(
- $args{type_constraint} && ref($args{type_constraint}) &&
- ($args{type_constraint}->isa('Moose::Meta::TypeConstraint') ||
- $args{type_constraint}->isa('MooseX::Types::UndefinedType'))
- ) {
- return bless \%args, $class;
+ my $class = shift @_;
+ if(my $arg = shift @_) {
+ if(ref $arg && $arg->isa('Moose::Meta::TypeConstraint')) {
+ return bless {'__type_constraint'=>$arg}, $class;
+ } elsif(ref $arg && $arg->isa('MooseX::Types::UndefinedType')) {
+ ## stub in case we'll need to handle these types differently
+ return bless {'__type_constraint'=>$arg}, $class;
+ } else {
+ croak "Argument must be ->isa('Moose::Meta::TypeConstraint') or ->isa('MooseX::Types::UndefinedType')";
+ }
} else {
- croak "The argument 'type_constraint' is not valid.";
+ croak "This method [new] requires a single argument";
}
-
}
=head type_constraint ($type_constraint)
=cut
-sub type_constraint {
+sub __type_constraint {
my $self = shift @_;
if(defined(my $tc = shift @_)) {
- $self->{type_constraint} = $tc;
+ $self->{__type_constraint} = $tc;
}
- return $self->{type_constraint};
+ return $self->{__type_constraint};
}
=head2 isa
sub isa {
my ($self, $target) = @_;
if(defined $target) {
- my $isa = $self->type_constraint->isa($target);
- return $isa;
+ return $self->__type_constraint->isa($target);
} else {
return;
}
sub can {
my ($self, $target) = @_;
if(defined $target) {
- my $can = $self->type_constraint->can($target);
- return $can;
+ return $self->__type_constraint->can($target);
} else {
return;
}
=cut
sub AUTOLOAD {
+ my ($self, @args) = @_;
my ($method) = (our $AUTOLOAD =~ /([^:]+)$/);
- return shift->type_constraint->$method(@_);
+ if($self->__type_constraint->can($method)) {
+ return $self->__type_constraint->$method(@args);
+ } else {
+ croak "Method '$method' is not supported";
+ }
}
=head1 AUTHOR AND COPYRIGHT
has 'StrOrArrayRef' => (is=>'rw', isa=>StrOrArrayRef);
has 'AtLeastOneInt' => (is=>'rw', isa=>AtLeastOneInt);
has 'pipeoverloading' => (is=>'rw', isa=>Int|Str);
- has 'deep' => (is=>'rw', isa=>ArrayRef([ArrayRef([HashRef([Int])])]));
+ #has 'deep' => (is=>'rw', isa=>ArrayRef([ArrayRef([HashRef([Int])])]));
+
+ has 'deep' => (is=>'rw', isa=>ArrayRef[ArrayRef[HashRef[Int]]] );
+
}
## Make sure we have a 'create object sanity check'
package DecoratorLibrary;
-use warnings;
-use strict;
-
use MooseX::Types::Moose qw( Str ArrayRef HashRef Int );
use MooseX::Types
-declare => [qw(
AtLeastOneInt
)];
+## Some questionable messing around
+ sub my_subtype {
+ my ($subtype, $basetype, @rest) = @_;
+ return subtype($subtype, $basetype, shift @rest, shift @rest);
+ }
+
+ sub my_from {
+ return @_;
+
+ }
+ sub my_as {
+ return @_;
+ }
+## End
+
subtype MyArrayRefBase,
as ArrayRef;
from MyHashRefOfStr,
via {[ sort map { length $_ } values(%$_) ]},
## Can't do HashRef[ArrayRef] here since if I do HashRef get the via {}
- ## Stuff passed as args.
- from HashRef([ArrayRef]),
+ ## Stuff passed as args and the associated prototype messed with it. MST
+ ## seems to have a line on it but might not fix fixable.
+ from (HashRef[ArrayRef]),
via {[ sort map { @$_ } values(%$_) ]};
subtype StrOrArrayRef,
as Str|ArrayRef;
-
+
subtype AtLeastOneInt,
## Same problem as MyArrayRefInt02, see above. Another way to solve it by
## forcing some sort of context. Tried to fix this with method prototypes
## but just couldn't make it work.
as (ArrayRef[Int]),
where { @$_ > 0 };
+
1;