2 package Moose::Util::TypeConstraints;
8 use Sub::Name 'subname';
9 use Scalar::Util 'blessed';
11 our $VERSION = '0.02';
13 use Moose::Meta::TypeConstraint;
17 my $pkg = shift || caller();
18 return if $pkg eq ':no_export';
20 foreach my $export (qw(type subtype as where coerce from via)) {
21 *{"${pkg}::${export}"} = \&{"${export}"};
27 sub find_type_constraint {
28 my $type_name = shift;
32 sub register_type_constraint {
33 my ($type_name, $type_constraint) = @_;
34 (not exists $TYPES{$type_name})
35 || confess "The type constraint '$type_name' has already been registered";
36 $TYPES{$type_name} = Moose::Meta::TypeConstraint->new(
38 constraint_code => $type_constraint
42 sub dump_type_constraints {
44 $Data::Dumper::Deparse = 1;
45 Data::Dumper::Dumper(\%TYPES);
48 sub export_type_contstraints_as_functions {
51 foreach my $constraint (keys %TYPES) {
52 *{"${pkg}::${constraint}"} = $TYPES{$constraint}->constraint_code;
56 sub find_type_coercion {
57 my $type_name = shift;
58 $TYPES{$type_name}->coercion_code;
61 sub register_type_coercion {
62 my ($type_name, $type_coercion) = @_;
63 my $type = $TYPES{$type_name};
64 (!$type->has_coercion)
65 || confess "The type coercion for '$type_name' has already been registered";
66 $type->set_coercion_code($type_coercion);
72 my ($name, $check) = @_;
73 my $full_name = caller() . "::${name}";
74 register_type_constraint($name => subname $full_name => sub {
76 return undef unless $check->($_[0]);
82 my ($name, $parent, $check) = @_;
84 my $full_name = caller() . "::${name}";
85 $parent = find_type_constraint($parent)->constraint_code
86 unless $parent && ref($parent) eq 'CODE';
87 register_type_constraint($name => subname $full_name => sub {
89 return undef unless defined $parent->($_[0]) && $check->($_[0]);
94 ($parent, $check) = ($name, $parent);
95 $parent = find_type_constraint($parent)->constraint_code
96 unless $parent && ref($parent) eq 'CODE';
97 return subname '__anon_subtype__' => sub {
99 return undef unless defined $parent->($_[0]) && $check->($_[0]);
106 my ($type_name, @coercion_map) = @_;
108 #warn Dumper \@coercion_map;
110 while (@coercion_map) {
111 my ($constraint_name, $action) = splice(@coercion_map, 0, 2);
112 my $constraint = find_type_constraint($constraint_name)->constraint_code;
113 (defined $constraint)
114 || confess "Could not find the type constraint ($constraint_name)";
115 push @coercions => [ $constraint, $action ];
117 register_type_coercion($type_name, sub {
119 foreach my $coercion (@coercions) {
120 my ($constraint, $converter) = @$coercion;
121 if (defined $constraint->($thing)) {
123 return $converter->($thing);
131 sub from ($) { $_[0] }
132 sub where (&) { $_[0] }
133 sub via (&) { $_[0] }
135 # define some basic types
137 type Any => where { 1 };
139 type Value => where { !ref($_) };
140 type Ref => where { ref($_) };
142 subtype Int => as Value => where { Scalar::Util::looks_like_number($_) };
143 subtype Str => as Value => where { !Scalar::Util::looks_like_number($_) };
145 subtype ScalarRef => as Ref => where { ref($_) eq 'SCALAR' };
146 subtype ArrayRef => as Ref => where { ref($_) eq 'ARRAY' };
147 subtype HashRef => as Ref => where { ref($_) eq 'HASH' };
148 subtype CodeRef => as Ref => where { ref($_) eq 'CODE' };
149 subtype RegexpRef => as Ref => where { ref($_) eq 'Regexp' };
152 # blessed(qr/.../) returns true,.. how odd
153 subtype Object => as Ref => where { blessed($_) && blessed($_) ne 'Regexp' };
163 Moose::Util::TypeConstraints - Type constraint system for Moose
167 use Moose::Util::TypeConstraints;
169 type Num => where { Scalar::Util::looks_like_number($_) };
175 subtype NaturalLessThanTen
177 => where { $_ < 10 };
185 This module provides Moose with the ability to create type contraints
186 to be are used in both attribute definitions and for method argument
189 This is B<NOT> a type system for Perl 5.
191 This module also provides a simple hierarchy for Perl 5 types, this
192 could probably use some work, but it works for me at the moment.
206 Suggestions for improvement are welcome.
210 =head2 Type Constraint Registry
214 =item B<find_type_constraint ($type_name)>
216 =item B<register_type_constraint ($type_name, $type_constraint)>
218 =item B<find_type_coercion>
220 =item B<register_type_coercion>
222 =item B<export_type_contstraints_as_functions>
224 =item B<dump_type_constraints>
228 =head2 Type Constraint Constructors
248 =head2 Built-in Type Constraints
278 All complex software has bugs lurking in it, and this module is no
279 exception. If you find a bug please either email me, or add the bug
284 Stevan Little E<lt>stevan@iinteractive.comE<gt>
286 =head1 COPYRIGHT AND LICENSE
288 Copyright 2006 by Infinity Interactive, Inc.
290 L<http://www.iinteractive.com>
292 This library is free software; you can redistribute it and/or modify
293 it under the same terms as Perl itself.