2 package Moose::Util::TypeConstraints;
5 use List::MoreUtils qw( all any );
6 use Scalar::Util qw( blessed reftype );
9 ## --------------------------------------------------------
10 # Prototyped subs must be predeclared because we have a
11 # circular dependency with Moose::Meta::Attribute et. al.
12 # so in case of us being use'd first the predeclaration
13 # ensures the prototypes are in scope when consumers are
22 ## --------------------------------------------------------
24 use Moose::Deprecated;
25 use Moose::Meta::TypeConstraint;
26 use Moose::Meta::TypeConstraint::Union;
27 use Moose::Meta::TypeConstraint::Parameterized;
28 use Moose::Meta::TypeConstraint::Parameterizable;
29 use Moose::Meta::TypeConstraint::Class;
30 use Moose::Meta::TypeConstraint::Role;
31 use Moose::Meta::TypeConstraint::Enum;
32 use Moose::Meta::TypeConstraint::DuckType;
33 use Moose::Meta::TypeCoercion;
34 use Moose::Meta::TypeCoercion::Union;
35 use Moose::Meta::TypeConstraint::Registry;
36 use Moose::Util::TypeConstraints::OptimizedConstraints;
38 Moose::Exporter->setup_import_methods(
41 type subtype class_type role_type maybe_type duck_type
42 as where message optimize_as
46 register_type_constraint
51 ## --------------------------------------------------------
52 ## type registry and some useful functions for it
53 ## --------------------------------------------------------
55 my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
57 sub get_type_constraint_registry {$REGISTRY}
58 sub list_all_type_constraints { keys %{ $REGISTRY->type_constraints } }
60 sub export_type_constraints_as_functions {
63 foreach my $constraint ( keys %{ $REGISTRY->type_constraints } ) {
64 my $tc = $REGISTRY->get_type_constraint($constraint)
65 ->_compiled_type_constraint;
66 *{"${pkg}::${constraint}"}
67 = sub { $tc->( $_[0] ) ? 1 : undef }; # the undef is for compat
71 sub create_type_constraint_union {
72 my @type_constraint_names;
74 if ( scalar @_ == 1 && _detect_type_constraint_union( $_[0] ) ) {
75 @type_constraint_names = _parse_type_constraint_union( $_[0] );
78 @type_constraint_names = @_;
81 ( scalar @type_constraint_names >= 2 )
82 || __PACKAGE__->_throw_error(
83 "You must pass in at least 2 type names to make a union");
85 my @type_constraints = map {
86 find_or_parse_type_constraint($_)
87 || __PACKAGE__->_throw_error(
88 "Could not locate type constraint ($_) for the union");
89 } @type_constraint_names;
91 return Moose::Meta::TypeConstraint::Union->new(
92 type_constraints => \@type_constraints );
95 sub create_parameterized_type_constraint {
96 my $type_constraint_name = shift;
97 my ( $base_type, $type_parameter )
98 = _parse_parameterized_type_constraint($type_constraint_name);
100 ( defined $base_type && defined $type_parameter )
101 || __PACKAGE__->_throw_error(
102 "Could not parse type name ($type_constraint_name) correctly");
104 if ( $REGISTRY->has_type_constraint($base_type) ) {
105 my $base_type_tc = $REGISTRY->get_type_constraint($base_type);
106 return _create_parameterized_type_constraint(
112 __PACKAGE__->_throw_error(
113 "Could not locate the base type ($base_type)");
117 sub _create_parameterized_type_constraint {
118 my ( $base_type_tc, $type_parameter ) = @_;
119 if ( $base_type_tc->can('parameterize') ) {
120 return $base_type_tc->parameterize($type_parameter);
123 return Moose::Meta::TypeConstraint::Parameterized->new(
124 name => $base_type_tc->name . '[' . $type_parameter . ']',
125 parent => $base_type_tc,
127 find_or_create_isa_type_constraint($type_parameter),
132 #should we also support optimized checks?
133 sub create_class_type_constraint {
134 my ( $class, $options ) = @_;
136 # too early for this check
137 #find_type_constraint("ClassName")->check($class)
138 # || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
146 $options{name} ||= "__ANON__";
148 Moose::Meta::TypeConstraint::Class->new(%options);
151 sub create_role_type_constraint {
152 my ( $role, $options ) = @_;
154 # too early for this check
155 #find_type_constraint("ClassName")->check($class)
156 # || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
164 $options{name} ||= "__ANON__";
166 Moose::Meta::TypeConstraint::Role->new(%options);
169 sub find_or_create_type_constraint {
170 my ( $type_constraint_name, $options_for_anon_type ) = @_;
173 = find_or_parse_type_constraint($type_constraint_name) ) {
176 elsif ( defined $options_for_anon_type ) {
179 # if there is no $options_for_anon_type
180 # specified, then we assume they don't
181 # want to create one, and return nothing.
183 # otherwise assume that we should create
184 # an ANON type with the $options_for_anon_type
185 # options which can be passed in. It should
186 # be noted that these don't get registered
187 # so we need to return it.
189 return Moose::Meta::TypeConstraint->new(
191 %{$options_for_anon_type}
198 sub find_or_create_isa_type_constraint {
199 my $type_constraint_name = shift;
200 find_or_parse_type_constraint($type_constraint_name)
201 || create_class_type_constraint($type_constraint_name);
204 sub find_or_create_does_type_constraint {
205 my $type_constraint_name = shift;
206 find_or_parse_type_constraint($type_constraint_name)
207 || create_role_type_constraint($type_constraint_name);
210 sub find_or_parse_type_constraint {
211 my $type_constraint_name = normalize_type_constraint_name(shift);
214 if ( $constraint = find_type_constraint($type_constraint_name) ) {
217 elsif ( _detect_type_constraint_union($type_constraint_name) ) {
218 $constraint = create_type_constraint_union($type_constraint_name);
220 elsif ( _detect_parameterized_type_constraint($type_constraint_name) ) {
222 = create_parameterized_type_constraint($type_constraint_name);
228 $REGISTRY->add_type_constraint($constraint);
232 sub normalize_type_constraint_name {
233 my $type_constraint_name = shift;
234 $type_constraint_name =~ s/\s//g;
235 return $type_constraint_name;
241 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
242 Carp::confess($error);
245 ## --------------------------------------------------------
246 ## exported functions ...
247 ## --------------------------------------------------------
249 sub find_type_constraint {
252 if ( blessed $type and $type->isa("Moose::Meta::TypeConstraint") ) {
256 return unless $REGISTRY->has_type_constraint($type);
257 return $REGISTRY->get_type_constraint($type);
261 sub register_type_constraint {
262 my $constraint = shift;
263 __PACKAGE__->_throw_error("can't register an unnamed type constraint")
264 unless defined $constraint->name;
265 $REGISTRY->add_type_constraint($constraint);
273 # back-compat version, called without sugar
274 if ( !any { ( reftype($_) || '' ) eq 'HASH' } @_ ) {
275 Moose::Deprecated::deprecated(
276 feature => 'type without sugar',
278 'Calling type() with a simple list of parameters is deprecated'
281 return _create_type_constraint( $_[0], undef, $_[1] );
286 my %p = map { %{$_} } @_;
288 return _create_type_constraint(
289 $name, undef, $p{where}, $p{message},
296 # crazy back-compat code for being called without sugar ...
298 # subtype 'Parent', sub { where };
299 if ( scalar @_ == 2 && ( reftype( $_[1] ) || '' ) eq 'CODE' ) {
300 Moose::Deprecated::deprecated(
301 feature => 'subtype without sugar',
303 'Calling subtype() with a simple list of parameters is deprecated'
306 return _create_type_constraint( undef, @_ );
309 # subtype 'Parent', sub { where }, sub { message };
310 # subtype 'Parent', sub { where }, sub { message }, sub { optimized };
311 if ( scalar @_ >= 3 && all { ( reftype($_) || '' ) eq 'CODE' }
313 Moose::Deprecated::deprecated(
314 feature => 'subtype without sugar',
316 'Calling subtype() with a simple list of parameters is deprecated'
319 return _create_type_constraint( undef, @_ );
322 # subtype 'Name', 'Parent', ...
323 if ( scalar @_ >= 2 && all { !ref } @_[ 0, 1 ] ) {
324 Moose::Deprecated::deprecated(
325 feature => 'subtype without sugar',
327 'Calling subtype() with a simple list of parameters is deprecated'
330 return _create_type_constraint(@_);
333 if ( @_ == 1 && !ref $_[0] ) {
334 __PACKAGE__->_throw_error(
335 'A subtype cannot consist solely of a name, it must have a parent'
339 # The blessed check is mostly to accommodate MooseX::Types, which
340 # uses an object which overloads stringification as a type name.
341 my $name = ref $_[0] && !blessed $_[0] ? undef : shift;
343 my %p = map { %{$_} } @_;
345 # subtype Str => where { ... };
346 if ( !exists $p{as} ) {
351 return _create_type_constraint(
352 $name, $p{as}, $p{where}, $p{message},
358 register_type_constraint(
359 create_class_type_constraint(
361 ( defined( $_[1] ) ? $_[1] : () ),
366 sub role_type ($;$) {
367 register_type_constraint(
368 create_role_type_constraint(
370 ( defined( $_[1] ) ? $_[1] : () ),
376 my ($type_parameter) = @_;
378 register_type_constraint(
379 $REGISTRY->get_type_constraint('Maybe')->parameterize($type_parameter)
384 my ( $type_name, @methods ) = @_;
385 if ( ref $type_name eq 'ARRAY' && !@methods ) {
386 @methods = @$type_name;
389 if ( @methods == 1 && ref $methods[0] eq 'ARRAY' ) {
390 @methods = @{ $methods[0] };
393 register_type_constraint(
394 create_duck_type_constraint(
402 my ( $type_name, @coercion_map ) = @_;
403 _install_type_coercions( $type_name, \@coercion_map );
406 # The trick of returning @_ lets us avoid having to specify a
407 # prototype. Perl will parse this:
415 # subtype( 'Foo', as( 'Str', where { ... } ) );
417 # If as() returns all it's extra arguments, this just works, and
418 # preserves backwards compatibility.
419 sub as { { as => shift }, @_ }
420 sub where (&) { { where => $_[0] } }
421 sub message (&) { { message => $_[0] } }
422 sub optimize_as (&) { { optimize_as => $_[0] } }
425 sub via (&) { $_[0] }
428 my ( $type_name, @values ) = @_;
431 # if only an array-ref is passed then
432 # you get an anon-enum
434 if ( ref $type_name eq 'ARRAY' ) {
436 || __PACKAGE__->_throw_error("enum called with an array reference and additional arguments. Did you mean to parenthesize the enum call's parameters?");
438 @values = @$type_name;
441 if ( @values == 1 && ref $values[0] eq 'ARRAY' ) {
442 @values = @{ $values[0] };
445 register_type_constraint(
446 create_enum_type_constraint(
453 sub create_enum_type_constraint {
454 my ( $type_name, $values ) = @_;
456 Moose::Meta::TypeConstraint::Enum->new(
457 name => $type_name || '__ANON__',
462 sub create_duck_type_constraint {
463 my ( $type_name, $methods ) = @_;
465 Moose::Meta::TypeConstraint::DuckType->new(
466 name => $type_name || '__ANON__',
472 my ($to_match, @cases) = @_;
474 if (@cases % 2 != 0) {
475 $default = pop @cases;
476 (ref $default eq 'CODE')
477 || __PACKAGE__->_throw_error("Default case must be a CODE ref, not $default");
480 my ($type, $action) = splice @cases, 0, 2;
482 unless (blessed $type && $type->isa('Moose::Meta::TypeConstraint')) {
483 $type = find_or_parse_type_constraint($type)
484 || __PACKAGE__->_throw_error("Cannot find or parse the type '$type'")
487 (ref $action eq 'CODE')
488 || __PACKAGE__->_throw_error("Match action must be a CODE ref, not $action");
490 if ($type->check($to_match)) {
491 local $_ = $to_match;
492 return $action->($to_match);
496 || __PACKAGE__->_throw_error("No cases matched for $to_match");
498 local $_ = $to_match;
499 return $default->($to_match);
504 ## --------------------------------------------------------
505 ## desugaring functions ...
506 ## --------------------------------------------------------
508 sub _create_type_constraint ($$$;$$) {
513 my $optimized = shift;
515 my $pkg_defined_in = scalar( caller(1) );
517 if ( defined $name ) {
518 my $type = $REGISTRY->get_type_constraint($name);
520 ( $type->_package_defined_in eq $pkg_defined_in )
522 "The type constraint '$name' has already been created in "
523 . $type->_package_defined_in
524 . " and cannot be created again in "
528 $name =~ /^[\w:\.]+$/
529 or die qq{$name contains invalid characters for a type name.}
530 . qq{ Names can contain alphanumeric character, ":", and "."\n};
535 package_defined_in => $pkg_defined_in,
537 ( $check ? ( constraint => $check ) : () ),
538 ( $message ? ( message => $message ) : () ),
539 ( $optimized ? ( optimized => $optimized ) : () ),
548 : find_or_create_isa_type_constraint($parent)
550 $constraint = $parent->create_child_type(%opts);
553 $constraint = Moose::Meta::TypeConstraint->new(%opts);
556 $REGISTRY->add_type_constraint($constraint)
562 sub _install_type_coercions ($$) {
563 my ( $type_name, $coercion_map ) = @_;
564 my $type = find_type_constraint($type_name);
566 || __PACKAGE__->_throw_error(
567 "Cannot find type '$type_name', perhaps you forgot to load it");
568 if ( $type->has_coercion ) {
569 $type->coercion->add_type_coercions(@$coercion_map);
572 my $type_coercion = Moose::Meta::TypeCoercion->new(
573 type_coercion_map => $coercion_map,
574 type_constraint => $type
576 $type->coercion($type_coercion);
580 ## --------------------------------------------------------
581 ## type notation parsing ...
582 ## --------------------------------------------------------
586 # All I have to say is mugwump++ cause I know
587 # do not even have enough regexp-fu to be able
588 # to have written this (I can only barely
589 # understand it as it is)
594 my $valid_chars = qr{[\w:\.]};
595 my $type_atom = qr{ (?>$valid_chars+) }x;
596 my $ws = qr{ (?>\s*) }x;
597 my $op_union = qr{ $ws \| $ws }x;
599 my ($type, $type_capture_parts, $type_with_parameter, $union, $any);
600 if (Class::MOP::IS_RUNNING_ON_5_10) {
602 = q{ (?&type_atom) (?: \[ (?&ws) (?&any) (?&ws) \] )? };
603 my $type_capture_parts_pattern
604 = q{ ((?&type_atom)) (?: \[ (?&ws) ((?&any)) (?&ws) \] )? };
605 my $type_with_parameter_pattern
606 = q{ (?&type_atom) \[ (?&ws) (?&any) (?&ws) \] };
608 = q{ (?&type) (?> (?: (?&op_union) (?&type) )+ ) };
610 = q{ (?&type) | (?&union) };
612 my $defines = qr{(?(DEFINE)
613 (?<valid_chars> $valid_chars)
614 (?<type_atom> $type_atom)
616 (?<op_union> $op_union)
617 (?<type> $type_pattern)
618 (?<type_capture_parts> $type_capture_parts_pattern)
619 (?<type_with_parameter> $type_with_parameter_pattern)
620 (?<union> $union_pattern)
621 (?<any> $any_pattern)
624 $type = qr{ $type_pattern $defines }x;
625 $type_capture_parts = qr{ $type_capture_parts_pattern $defines }x;
626 $type_with_parameter = qr{ $type_with_parameter_pattern $defines }x;
627 $union = qr{ $union_pattern $defines }x;
628 $any = qr{ $any_pattern $defines }x;
632 = qr{ $type_atom (?: \[ $ws (??{$any}) $ws \] )? }x;
634 = qr{ ($type_atom) (?: \[ $ws ((??{$any})) $ws \] )? }x;
636 = qr{ $type_atom \[ $ws (??{$any}) $ws \] }x;
638 = qr{ $type (?> (?: $op_union $type )+ ) }x;
640 = qr{ $type | $union }x;
644 sub _parse_parameterized_type_constraint {
645 { no warnings 'void'; $any; } # force capture of interpolated lexical
646 $_[0] =~ m{ $type_capture_parts }x;
650 sub _detect_parameterized_type_constraint {
651 { no warnings 'void'; $any; } # force capture of interpolated lexical
652 $_[0] =~ m{ ^ $type_with_parameter $ }x;
655 sub _parse_type_constraint_union {
656 { no warnings 'void'; $any; } # force capture of interpolated lexical
659 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
662 ( pos($given) eq length($given) )
663 || __PACKAGE__->_throw_error( "'$given' didn't parse (parse-pos="
671 sub _detect_type_constraint_union {
672 { no warnings 'void'; $any; } # force capture of interpolated lexical
673 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
677 ## --------------------------------------------------------
678 # define some basic built-in types
679 ## --------------------------------------------------------
681 # By making these classes immutable before creating all the types we
682 # below, we avoid repeatedly calling the slow MOP-based accessors.
684 inline_constructor => 1,
685 constructor_name => "_new",
687 # these are Class::MOP accessors, so they need inlining
688 inline_accessors => 1
689 ) for grep { $_->is_mutable }
690 map { Class::MOP::class_of($_) }
692 Moose::Meta::TypeConstraint
693 Moose::Meta::TypeConstraint::Union
694 Moose::Meta::TypeConstraint::Parameterized
695 Moose::Meta::TypeConstraint::Parameterizable
696 Moose::Meta::TypeConstraint::Class
697 Moose::Meta::TypeConstraint::Role
698 Moose::Meta::TypeConstraint::Enum
699 Moose::Meta::TypeConstraint::DuckType
700 Moose::Meta::TypeConstraint::Registry
703 type 'Any' => where {1}; # meta-type including all
704 subtype 'Item' => as 'Any'; # base-type
706 subtype 'Undef' => as 'Item' => where { !defined($_) };
707 subtype 'Defined' => as 'Item' => where { defined($_) };
709 subtype 'Bool' => as 'Item' =>
710 where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
712 subtype 'Value' => as 'Defined' => where { !ref($_) } =>
713 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Value;
715 subtype 'Ref' => as 'Defined' => where { ref($_) } =>
716 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Ref;
718 subtype 'Str' => as 'Value' => where { ref(\$_) eq 'SCALAR' } =>
719 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
721 subtype 'Num' => as 'Str' =>
722 where { Scalar::Util::looks_like_number($_) } =>
723 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
725 subtype 'Int' => as 'Num' => where { "$_" =~ /^-?[0-9]+$/ } =>
726 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Int;
728 subtype 'CodeRef' => as 'Ref' => where { ref($_) eq 'CODE' } =>
729 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::CodeRef;
730 subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } =>
732 \&Moose::Util::TypeConstraints::OptimizedConstraints::RegexpRef;
733 subtype 'GlobRef' => as 'Ref' => where { ref($_) eq 'GLOB' } =>
734 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::GlobRef;
737 # scalar filehandles are GLOB refs,
738 # but a GLOB ref is not always a filehandle
739 subtype 'FileHandle' => as 'GlobRef' => where {
740 Scalar::Util::openhandle($_) || ( blessed($_) && $_->isa("IO::Handle") );
742 \&Moose::Util::TypeConstraints::OptimizedConstraints::FileHandle;
745 # blessed(qr/.../) returns true,.. how odd
746 subtype 'Object' => as 'Ref' =>
747 where { blessed($_) && blessed($_) ne 'Regexp' } =>
748 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
750 # This type is deprecated.
751 subtype 'Role' => as 'Object' => where { $_->can('does') } =>
752 optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
754 my $_class_name_checker = sub { };
756 subtype 'ClassName' => as 'Str' =>
757 where { Class::MOP::is_class_loaded($_) } => optimize_as
758 \&Moose::Util::TypeConstraints::OptimizedConstraints::ClassName;
760 subtype 'RoleName' => as 'ClassName' => where {
761 (Class::MOP::class_of($_) || return)->isa('Moose::Meta::Role');
763 \&Moose::Util::TypeConstraints::OptimizedConstraints::RoleName;
765 ## --------------------------------------------------------
766 # parameterizable types ...
768 $REGISTRY->add_type_constraint(
769 Moose::Meta::TypeConstraint::Parameterizable->new(
771 package_defined_in => __PACKAGE__,
772 parent => find_type_constraint('Ref'),
773 constraint => sub { ref($_) eq 'SCALAR' || ref($_) eq 'REF' },
775 \&Moose::Util::TypeConstraints::OptimizedConstraints::ScalarRef,
776 constraint_generator => sub {
777 my $type_parameter = shift;
778 my $check = $type_parameter->_compiled_type_constraint;
780 return $check->(${ $_ });
786 $REGISTRY->add_type_constraint(
787 Moose::Meta::TypeConstraint::Parameterizable->new(
789 package_defined_in => __PACKAGE__,
790 parent => find_type_constraint('Ref'),
791 constraint => sub { ref($_) eq 'ARRAY' },
793 \&Moose::Util::TypeConstraints::OptimizedConstraints::ArrayRef,
794 constraint_generator => sub {
795 my $type_parameter = shift;
796 my $check = $type_parameter->_compiled_type_constraint;
798 foreach my $x (@$_) {
799 ( $check->($x) ) || return;
807 $REGISTRY->add_type_constraint(
808 Moose::Meta::TypeConstraint::Parameterizable->new(
810 package_defined_in => __PACKAGE__,
811 parent => find_type_constraint('Ref'),
812 constraint => sub { ref($_) eq 'HASH' },
814 \&Moose::Util::TypeConstraints::OptimizedConstraints::HashRef,
815 constraint_generator => sub {
816 my $type_parameter = shift;
817 my $check = $type_parameter->_compiled_type_constraint;
819 foreach my $x ( values %$_ ) {
820 ( $check->($x) ) || return;
828 $REGISTRY->add_type_constraint(
829 Moose::Meta::TypeConstraint::Parameterizable->new(
831 package_defined_in => __PACKAGE__,
832 parent => find_type_constraint('Item'),
833 constraint => sub {1},
834 constraint_generator => sub {
835 my $type_parameter = shift;
836 my $check = $type_parameter->_compiled_type_constraint;
838 return 1 if not( defined($_) ) || $check->($_);
845 my @PARAMETERIZABLE_TYPES
846 = map { $REGISTRY->get_type_constraint($_) } qw[ScalarRef ArrayRef HashRef Maybe];
848 sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
850 sub add_parameterizable_type {
853 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
854 || __PACKAGE__->_throw_error(
855 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
857 push @PARAMETERIZABLE_TYPES => $type;
860 ## --------------------------------------------------------
861 # end of built-in types ...
862 ## --------------------------------------------------------
865 my @BUILTINS = list_all_type_constraints();
866 sub list_all_builtin_type_constraints {@BUILTINS}
873 goto &Moose::throw_error;
878 # ABSTRACT: Type constraint system for Moose
886 use Moose::Util::TypeConstraints;
892 subtype 'NaturalLessThanTen'
895 => message { "This number ($_) is not less than ten!" };
901 enum 'RGBColors' => qw(red green blue);
903 no Moose::Util::TypeConstraints;
907 This module provides Moose with the ability to create custom type
908 constraints to be used in attribute definition.
910 =head2 Important Caveat
912 This is B<NOT> a type system for Perl 5. These are type constraints,
913 and they are not used by Moose unless you tell it to. No type
914 inference is performed, expressions are not typed, etc. etc. etc.
916 A type constraint is at heart a small "check if a value is valid"
917 function. A constraint can be associated with an attribute. This
918 simplifies parameter validation, and makes your code clearer to read,
919 because you can refer to constraints by name.
921 =head2 Slightly Less Important Caveat
923 It is B<always> a good idea to quote your type names.
925 This prevents Perl from trying to execute the call as an indirect
926 object call. This can be an issue when you have a subtype with the
927 same name as a valid class.
931 subtype DateTime => as Object => where { $_->isa('DateTime') };
933 will I<just work>, while this:
936 subtype DateTime => as Object => where { $_->isa('DateTime') };
938 will fail silently and cause many headaches. The simple way to solve
939 this, as well as future proof your subtypes from classes which have
940 yet to have been created, is to quote the type name:
943 subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
945 =head2 Default Type Constraints
947 This module also provides a simple hierarchy for Perl 5 types, here is
948 that hierarchy represented visually.
972 B<NOTE:> Any type followed by a type parameter C<[`a]> can be
973 parameterized, this means you can say:
975 ArrayRef[Int] # an array of integers
976 HashRef[CodeRef] # a hash of str to CODE ref mappings
977 ScalarRef[Int] # a reference to an integer
978 Maybe[Str] # value may be a string, may be undefined
980 If Moose finds a name in brackets that it does not recognize as an
981 existing type, it assumes that this is a class name, for example
982 C<ArrayRef[DateTime]>.
984 B<NOTE:> Unless you parameterize a type, then it is invalid to include
985 the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
986 name, I<not> as a parameterization of C<ArrayRef>.
988 B<NOTE:> The C<Undef> type constraint for the most part works
989 correctly now, but edge cases may still exist, please use it
992 B<NOTE:> The C<ClassName> type constraint does a complex package
993 existence check. This means that your class B<must> be loaded for this
994 type constraint to pass.
996 B<NOTE:> The C<RoleName> constraint checks a string is a I<package
997 name> which is a role, like C<'MyApp::Role::Comparable'>.
999 =head2 Type Constraint Naming
1001 Type name declared via this module can only contain alphanumeric
1002 characters, colons (:), and periods (.).
1004 Since the types created by this module are global, it is suggested
1005 that you namespace your types just as you would namespace your
1006 modules. So instead of creating a I<Color> type for your
1007 B<My::Graphics> module, you would call the type
1008 I<My::Graphics::Types::Color> instead.
1010 =head2 Use with Other Constraint Modules
1012 This module can play nicely with other constraint modules with some
1013 slight tweaking. The C<where> clause in types is expected to be a
1014 C<CODE> reference which checks it's first argument and returns a
1015 boolean. Since most constraint modules work in a similar way, it
1016 should be simple to adapt them to work with Moose.
1018 For instance, this is how you could use it with
1019 L<Declare::Constraints::Simple> to declare a completely new type.
1021 type 'HashOfArrayOfObjects',
1025 -values => IsArrayRef(IsObject)
1029 For more examples see the F<t/200_examples/004_example_w_DCS.t> test
1032 Here is an example of using L<Test::Deep> and it's non-test
1033 related C<eq_deeply> function.
1035 type 'ArrayOfHashOfBarsAndRandomNumbers'
1038 array_each(subhashof({
1040 random_number => ignore()
1044 For a complete example see the
1045 F<t/200_examples/005_example_w_TestDeep.t> test file.
1049 =head2 Type Constraint Constructors
1051 The following functions are used to create type constraints. They
1052 will also register the type constraints your create in a global
1053 registry that is used to look types up by name.
1055 See the L</SYNOPSIS> for an example of how to use these.
1059 =item B<< subtype 'Name' => as 'Parent' => where { } ... >>
1061 This creates a named subtype.
1063 If you provide a parent that Moose does not recognize, it will
1064 automatically create a new class type constraint for this name.
1066 When creating a named type, the C<subtype> function should either be
1067 called with the sugar helpers (C<where>, C<message>, etc), or with a
1068 name and a hashref of parameters:
1070 subtype( 'Foo', { where => ..., message => ... } );
1072 The valid hashref keys are C<as> (the parent), C<where>, C<message>,
1075 =item B<< subtype as 'Parent' => where { } ... >>
1077 This creates an unnamed subtype and will return the type
1078 constraint meta-object, which will be an instance of
1079 L<Moose::Meta::TypeConstraint>.
1081 When creating an anonymous type, the C<subtype> function should either
1082 be called with the sugar helpers (C<where>, C<message>, etc), or with
1083 just a hashref of parameters:
1085 subtype( { where => ..., message => ... } );
1087 =item B<class_type ($class, ?$options)>
1089 Creates a new subtype of C<Object> with the name C<$class> and the
1090 metaclass L<Moose::Meta::TypeConstraint::Class>.
1092 =item B<role_type ($role, ?$options)>
1094 Creates a C<Role> type constraint with the name C<$role> and the
1095 metaclass L<Moose::Meta::TypeConstraint::Role>.
1097 =item B<maybe_type ($type)>
1099 Creates a type constraint for either C<undef> or something of the
1102 =item B<duck_type ($name, \@methods)>
1104 This will create a subtype of Object and test to make sure the value
1105 C<can()> do the methods in C<\@methods>.
1107 This is intended as an easy way to accept non-Moose objects that
1108 provide a certain interface. If you're using Moose classes, we
1109 recommend that you use a C<requires>-only Role instead.
1111 =item B<duck_type (\@methods)>
1113 If passed an ARRAY reference as the only parameter instead of the
1114 C<$name>, C<\@methods> pair, this will create an unnamed duck type.
1115 This can be used in an attribute definition like so:
1119 isa => duck_type( [qw( get_set )] ),
1122 =item B<enum ($name, \@values)>
1124 This will create a basic subtype for a given set of strings.
1125 The resulting constraint will be a subtype of C<Str> and
1126 will match any of the items in C<\@values>. It is case sensitive.
1127 See the L</SYNOPSIS> for a simple example.
1129 B<NOTE:> This is not a true proper enum type, it is simply
1130 a convenient constraint builder.
1132 =item B<enum (\@values)>
1134 If passed an ARRAY reference as the only parameter instead of the
1135 C<$name>, C<\@values> pair, this will create an unnamed enum. This
1136 can then be used in an attribute definition like so:
1138 has 'sort_order' => (
1140 isa => enum([qw[ ascending descending ]]),
1143 =item B<as 'Parent'>
1145 This is just sugar for the type constraint construction syntax.
1147 It takes a single argument, which is the name of a parent type.
1149 =item B<where { ... }>
1151 This is just sugar for the type constraint construction syntax.
1153 It takes a subroutine reference as an argument. When the type
1154 constraint is tested, the reference is run with the value to be tested
1155 in C<$_>. This reference should return true or false to indicate
1156 whether or not the constraint check passed.
1158 =item B<message { ... }>
1160 This is just sugar for the type constraint construction syntax.
1162 It takes a subroutine reference as an argument. When the type
1163 constraint fails, then the code block is run with the value provided
1164 in C<$_>. This reference should return a string, which will be used in
1165 the text of the exception thrown.
1167 =item B<optimize_as { ... }>
1169 This can be used to define a "hand optimized" version of your
1170 type constraint which can be used to avoid traversing a subtype
1171 constraint hierarchy.
1173 B<NOTE:> You should only use this if you know what you are doing.
1174 All the built in types use this, so your subtypes (assuming they
1175 are shallow) will not likely need to use this.
1177 =item B<< type 'Name' => where { } ... >>
1179 This creates a base type, which has no parent.
1181 The C<type> function should either be called with the sugar helpers
1182 (C<where>, C<message>, etc), or with a name and a hashref of
1185 type( 'Foo', { where => ..., message => ... } );
1187 The valid hashref keys are C<where>, C<message>, and C<optimize_as>.
1191 =head2 Type Constraint Utilities
1195 =item B<< match_on_type $value => ( $type => \&action, ... ?\&default ) >>
1197 This is a utility function for doing simple type based dispatching similar to
1198 match/case in OCaml and case/of in Haskell. It is not as featureful as those
1199 languages, nor does not it support any kind of automatic destructuring
1200 bind. Here is a simple Perl pretty printer dispatching over the core Moose
1205 match_on_type $x => (
1210 join ", " => map { $_ . ' => ' . ppprint( $hash->{$_} ) }
1216 '[ ' . ( join ", " => map { ppprint($_) } @$array ) . ' ]';
1218 CodeRef => sub {'sub { ... }'},
1219 RegexpRef => sub { 'qr/' . $_ . '/' },
1220 GlobRef => sub { '*' . B::svref_2object($_)->NAME },
1221 Object => sub { $_->can('to_string') ? $_->to_string : $_ },
1222 ScalarRef => sub { '\\' . ppprint( ${$_} ) },
1224 Str => sub { '"' . $_ . '"' },
1225 Undef => sub {'undef'},
1226 => sub { die "I don't know what $_ is" }
1230 Or a simple JSON serializer:
1234 match_on_type $x => (
1240 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
1246 '[ ' . ( join ", " => map { to_json($_) } @$array ) . ' ]';
1249 Str => sub { '"' . $_ . '"' },
1250 Undef => sub {'null'},
1251 => sub { die "$_ is not acceptable json type" }
1255 The matcher is done by mapping a C<$type> to an C<\&action>. The C<$type> can
1256 be either a string type or a L<Moose::Meta::TypeConstraint> object, and
1257 C<\&action> is a subroutine reference. This function will dispatch on the
1258 first match for C<$value>. It is possible to have a catch-all by providing an
1259 additional subroutine reference as the final argument to C<match_on_type>.
1263 =head2 Type Coercion Constructors
1265 You can define coercions for type constraints, which allow you to
1266 automatically transform values to something valid for the type
1267 constraint. If you ask your accessor to coerce, then Moose will run
1268 the type-coercion code first, followed by the type constraint
1269 check. This feature should be used carefully as it is very powerful
1270 and could easily take off a limb if you are not careful.
1272 See the L</SYNOPSIS> for an example of how to use these.
1276 =item B<< coerce 'Name' => from 'OtherName' => via { ... } >>
1278 This defines a coercion from one type to another. The C<Name> argument
1279 is the type you are coercing I<to>.
1281 To define multiple coercions, supply more sets of from/via pairs:
1284 from 'OtherName' => via { ... },
1285 from 'ThirdName' => via { ... };
1287 =item B<from 'OtherName'>
1289 This is just sugar for the type coercion construction syntax.
1291 It takes a single type name (or type object), which is the type being
1294 =item B<via { ... }>
1296 This is just sugar for the type coercion construction syntax.
1298 It takes a subroutine reference. This reference will be called with
1299 the value to be coerced in C<$_>. It is expected to return a new value
1300 of the proper type for the coercion.
1304 =head2 Creating and Finding Type Constraints
1306 These are additional functions for creating and finding type
1307 constraints. Most of these functions are not available for
1308 importing. The ones that are importable as specified.
1312 =item B<find_type_constraint($type_name)>
1314 This function can be used to locate the L<Moose::Meta::TypeConstraint>
1315 object for a named type.
1317 This function is importable.
1319 =item B<register_type_constraint($type_object)>
1321 This function will register a L<Moose::Meta::TypeConstraint> with the
1322 global type registry.
1324 This function is importable.
1326 =item B<normalize_type_constraint_name($type_constraint_name)>
1328 This method takes a type constraint name and returns the normalized
1329 form. This removes any whitespace in the string.
1331 =item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
1333 This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1334 or a list of names. It returns a new
1335 L<Moose::Meta::TypeConstraint::Union> object.
1337 =item B<create_parameterized_type_constraint($type_name)>
1339 Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1340 this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1341 object. The C<BaseType> must exist already exist as a parameterizable
1344 =item B<create_class_type_constraint($class, $options)>
1346 Given a class name this function will create a new
1347 L<Moose::Meta::TypeConstraint::Class> object for that class name.
1349 The C<$options> is a hash reference that will be passed to the
1350 L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
1352 =item B<create_role_type_constraint($role, $options)>
1354 Given a role name this function will create a new
1355 L<Moose::Meta::TypeConstraint::Role> object for that role name.
1357 The C<$options> is a hash reference that will be passed to the
1358 L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
1360 =item B<create_enum_type_constraint($name, $values)>
1362 Given a enum name this function will create a new
1363 L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1365 =item B<create_duck_type_constraint($name, $methods)>
1367 Given a duck type name this function will create a new
1368 L<Moose::Meta::TypeConstraint::DuckType> object for that enum name.
1370 =item B<find_or_parse_type_constraint($type_name)>
1372 Given a type name, this first attempts to find a matching constraint
1373 in the global registry.
1375 If the type name is a union or parameterized type, it will create a
1376 new object of the appropriate, but if given a "regular" type that does
1377 not yet exist, it simply returns false.
1379 When given a union or parameterized type, the member or base type must
1382 If it creates a new union or parameterized type, it will add it to the
1385 =item B<find_or_create_isa_type_constraint($type_name)>
1387 =item B<find_or_create_does_type_constraint($type_name)>
1389 These functions will first call C<find_or_parse_type_constraint>. If
1390 that function does not return a type, a new anonymous type object will
1393 The C<isa> variant will use C<create_class_type_constraint> and the
1394 C<does> variant will use C<create_role_type_constraint>.
1396 =item B<get_type_constraint_registry>
1398 Returns the L<Moose::Meta::TypeConstraint::Registry> object which
1399 keeps track of all type constraints.
1401 =item B<list_all_type_constraints>
1403 This will return a list of type constraint names in the global
1404 registry. You can then fetch the actual type object using
1405 C<find_type_constraint($type_name)>.
1407 =item B<list_all_builtin_type_constraints>
1409 This will return a list of builtin type constraints, meaning those
1410 which are defined in this module. See the L<Default Type Constraints>
1411 section for a complete list.
1413 =item B<export_type_constraints_as_functions>
1415 This will export all the current type constraints as functions into
1416 the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1417 mostly used for testing, but it might prove useful to others.
1419 =item B<get_all_parameterizable_types>
1421 This returns all the parameterizable types that have been registered,
1422 as a list of type objects.
1424 =item B<add_parameterizable_type($type)>
1426 Adds C<$type> to the list of parameterizable types
1432 See L<Moose/BUGS> for details on reporting bugs.