2 package Moose::Util::TypeConstraints;
8 use Sub::Name 'subname';
9 use Scalar::Util 'blessed';
11 our $VERSION = '0.02';
15 my $pkg = shift || caller();
16 return if $pkg eq ':no_export';
18 foreach my $export (qw(type subtype coerce as where to)) {
19 *{"${pkg}::${export}"} = \&{"${export}"};
25 sub find_type_constraint {
26 my $type_name = shift;
30 sub register_type_constraint {
31 my ($type_name, $type_constraint) = @_;
32 $TYPES{$type_name} = $type_constraint;
35 sub export_type_contstraints_as_functions {
38 foreach my $constraint (keys %TYPES) {
39 *{"${pkg}::${constraint}"} = $TYPES{$constraint};
46 sub find_type_coercion {
47 my $type_name = shift;
48 $COERCIONS{$type_name};
51 sub register_type_coercion {
52 my ($type_name, $type_coercion) = @_;
53 $COERCIONS{$type_name} = $type_coercion;
59 my ($name, $check) = @_;
60 my $full_name = caller() . "::${name}";
61 register_type_constraint($name => subname $full_name => sub {
62 return find_type_constraint($name) unless defined $_[0];
64 return undef unless $check->($_[0]);
70 my ($name, $parent, $check) = @_;
72 my $full_name = caller() . "::${name}";
73 $parent = find_type_constraint($parent)
74 unless $parent && ref($parent) eq 'CODE';
75 register_type_constraint($name => subname $full_name => sub {
76 return find_type_constraint($name) unless defined $_[0];
78 return undef unless defined $parent->($_[0]) && $check->($_[0]);
83 ($parent, $check) = ($name, $parent);
84 $parent = find_type_constraint($parent)
85 unless $parent && ref($parent) eq 'CODE';
86 return subname '__anon_subtype__' => sub {
88 return undef unless defined $parent->($_[0]) && $check->($_[0]);
95 my ($type_name, @coercion_map) = @_;
97 while (@coercion_map) {
98 my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
99 my $constraint = find_type_constraint($constraint_name);
100 (defined $constraint)
101 || confess "Could not find the type constraint ($constraint_name)";
102 push @coercions => [ $constraint, $action ];
104 register_type_coercion($type_name, sub {
106 foreach my $coercion (@coercions) {
107 my ($constraint, $converter) = @$coercion;
108 if (defined $constraint->($thing)) {
109 return $converter->($thing);
117 sub where (&) { $_[0] }
120 # define some basic types
122 type Any => where { 1 };
124 type Value => where { !ref($_) };
125 type Ref => where { ref($_) };
127 subtype Int => as Value => where { Scalar::Util::looks_like_number($_) };
128 subtype Str => as Value => where { !Scalar::Util::looks_like_number($_) };
130 subtype ScalarRef => as Ref => where { ref($_) eq 'SCALAR' };
131 subtype ArrayRef => as Ref => where { ref($_) eq 'ARRAY' };
132 subtype HashRef => as Ref => where { ref($_) eq 'HASH' };
133 subtype CodeRef => as Ref => where { ref($_) eq 'CODE' };
134 subtype RegexpRef => as Ref => where { ref($_) eq 'Regexp' };
137 # blessed(qr/.../) returns true,.. how odd
138 subtype Object => as Ref => where { blessed($_) && blessed($_) ne 'Regexp' };
148 Moose::Util::TypeConstraints - Type constraint system for Moose
152 use Moose::Util::TypeConstraints;
154 type Num => where { Scalar::Util::looks_like_number($_) };
160 subtype NaturalLessThanTen
162 => where { $_ < 10 };
166 This module provides Moose with the ability to create type contraints
167 to be are used in both attribute definitions and for method argument
170 This is B<NOT> a type system for Perl 5.
172 The type and subtype constraints are basically functions which will
173 validate their first argument. If called with no arguments, they will
174 return themselves (this is syntactic sugar for Moose attributes).
176 This module also provides a simple hierarchy for Perl 5 types, this
177 could probably use some work, but it works for me at the moment.
191 Suggestions for improvement are welcome.
195 =head2 Type Constraint Registry
199 =item B<find_type_constraint ($type_name)>
201 =item B<register_type_constraint ($type_name, $type_constraint)>
203 =item B<find_type_coercion>
205 =item B<register_type_coercion>
207 =item B<export_type_contstraints_as_functions>
211 =head2 Type Constraint Constructors
229 =head2 Built-in Type Constraints
259 All complex software has bugs lurking in it, and this module is no
260 exception. If you find a bug please either email me, or add the bug
265 Stevan Little E<lt>stevan@iinteractive.comE<gt>
267 =head1 COPYRIGHT AND LICENSE
269 Copyright 2006 by Infinity Interactive, Inc.
271 L<http://www.iinteractive.com>
273 This library is free software; you can redistribute it and/or modify
274 it under the same terms as Perl itself.