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 as where to coerce)) {
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 dump_type_constraints {
37 $Data::Dumper::Deparse = 1;
38 Data::Dumper::Dumper(\%TYPES);
41 sub export_type_contstraints_as_functions {
44 foreach my $constraint (keys %TYPES) {
45 *{"${pkg}::${constraint}"} = $TYPES{$constraint};
52 sub find_type_coercion {
53 my $type_name = shift;
54 $COERCIONS{$type_name};
57 sub register_type_coercion {
58 my ($type_name, $type_coercion) = @_;
59 $COERCIONS{$type_name} = $type_coercion;
65 my ($name, $check) = @_;
66 my $full_name = caller() . "::${name}";
67 register_type_constraint($name => subname $full_name => sub {
68 return find_type_constraint($name) unless defined $_[0];
70 return undef unless $check->($_[0]);
76 my ($name, $parent, $check) = @_;
78 my $full_name = caller() . "::${name}";
79 $parent = find_type_constraint($parent)
80 unless $parent && ref($parent) eq 'CODE';
81 register_type_constraint($name => subname $full_name => sub {
82 return find_type_constraint($name) unless defined $_[0];
84 return undef unless defined $parent->($_[0]) && $check->($_[0]);
89 ($parent, $check) = ($name, $parent);
90 $parent = find_type_constraint($parent)
91 unless $parent && ref($parent) eq 'CODE';
92 return subname '__anon_subtype__' => sub {
94 return undef unless defined $parent->($_[0]) && $check->($_[0]);
101 my ($type_name, @coercion_map) = @_;
103 #warn Dumper \@coercion_map;
105 while (@coercion_map) {
106 my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
107 my $constraint = find_type_constraint($constraint_name);
108 (defined $constraint)
109 || confess "Could not find the type constraint ($constraint_name)";
110 push @coercions => [ $constraint, $action ];
112 register_type_coercion($type_name, sub {
114 foreach my $coercion (@coercions) {
115 my ($constraint, $converter) = @$coercion;
116 if (defined $constraint->($thing)) {
117 return $converter->($thing);
125 sub where (&) { $_[0] }
128 # define some basic types
130 type Any => where { 1 };
132 type Value => where { !ref($_) };
133 type Ref => where { ref($_) };
135 subtype Int => as Value => where { Scalar::Util::looks_like_number($_) };
136 subtype Str => as Value => where { !Scalar::Util::looks_like_number($_) };
138 subtype ScalarRef => as Ref => where { ref($_) eq 'SCALAR' };
139 subtype ArrayRef => as Ref => where { ref($_) eq 'ARRAY' };
140 subtype HashRef => as Ref => where { ref($_) eq 'HASH' };
141 subtype CodeRef => as Ref => where { ref($_) eq 'CODE' };
142 subtype RegexpRef => as Ref => where { ref($_) eq 'Regexp' };
145 # blessed(qr/.../) returns true,.. how odd
146 subtype Object => as Ref => where { blessed($_) && blessed($_) ne 'Regexp' };
156 Moose::Util::TypeConstraints - Type constraint system for Moose
160 use Moose::Util::TypeConstraints;
162 type Num => where { Scalar::Util::looks_like_number($_) };
168 subtype NaturalLessThanTen
170 => where { $_ < 10 };
174 This module provides Moose with the ability to create type contraints
175 to be are used in both attribute definitions and for method argument
178 This is B<NOT> a type system for Perl 5.
180 The type and subtype constraints are basically functions which will
181 validate their first argument. If called with no arguments, they will
182 return themselves (this is syntactic sugar for Moose attributes).
184 This module also provides a simple hierarchy for Perl 5 types, this
185 could probably use some work, but it works for me at the moment.
199 Suggestions for improvement are welcome.
203 =head2 Type Constraint Registry
207 =item B<find_type_constraint ($type_name)>
209 =item B<register_type_constraint ($type_name, $type_constraint)>
211 =item B<find_type_coercion>
213 =item B<register_type_coercion>
215 =item B<export_type_contstraints_as_functions>
217 =item B<dump_type_constraints>
221 =head2 Type Constraint Constructors
239 =head2 Built-in Type Constraints
269 All complex software has bugs lurking in it, and this module is no
270 exception. If you find a bug please either email me, or add the bug
275 Stevan Little E<lt>stevan@iinteractive.comE<gt>
277 =head1 COPYRIGHT AND LICENSE
279 Copyright 2006 by Infinity Interactive, Inc.
281 L<http://www.iinteractive.com>
283 This library is free software; you can redistribute it and/or modify
284 it under the same terms as Perl itself.