little better error message there
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
1
2 package Moose::Util::TypeConstraints;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'blessed', 'reftype';
9 use B            'svref_2object';
10 use Sub::Exporter;
11
12 our $VERSION   = '0.17';
13 our $AUTHORITY = 'cpan:STEVAN';
14
15 ## --------------------------------------------------------
16 # Prototyped subs must be predeclared because we have a
17 # circular dependency with Moose::Meta::Attribute et. al.
18 # so in case of us being use'd first the predeclaration
19 # ensures the prototypes are in scope when consumers are
20 # compiled.
21
22 # creation and location
23 sub find_type_constraint                 ($);
24 sub find_or_create_type_constraint       ($;$);
25 sub create_type_constraint_union         (@);
26 sub create_parameterized_type_constraint ($);
27
28 # dah sugah!
29 sub type        ($$;$$);
30 sub subtype     ($$;$$$);
31 sub coerce      ($@);
32 sub as          ($);
33 sub from        ($);
34 sub where       (&);
35 sub via         (&);
36 sub message     (&);
37 sub optimize_as (&);
38 sub enum        ($;@);
39
40 ## private stuff ...
41 sub _create_type_constraint ($$$;$$);
42 sub _install_type_coercions ($$);
43
44 ## --------------------------------------------------------
45
46 use Moose::Meta::TypeConstraint;
47 use Moose::Meta::TypeConstraint::Union;
48 use Moose::Meta::TypeConstraint::Parameterized;
49 use Moose::Meta::TypeCoercion;
50 use Moose::Meta::TypeCoercion::Union;
51 use Moose::Meta::TypeConstraint::Registry;
52
53 my @exports = qw/
54     type subtype as where message optimize_as
55     coerce from via
56     enum
57     find_type_constraint
58 /;
59
60 Sub::Exporter::setup_exporter({
61     exports => \@exports,
62     groups  => { default => [':all'] }
63 });
64
65 sub unimport {
66     no strict 'refs';
67     my $class = caller();
68     # loop through the exports ...
69     foreach my $name (@exports) {
70         # if we find one ...
71         if (defined &{$class . '::' . $name}) {
72             my $keyword = \&{$class . '::' . $name};
73
74             # make sure it is from Moose
75             my $pkg_name = eval { svref_2object($keyword)->GV->STASH->NAME };
76             next if $@;
77             next if $pkg_name ne 'Moose::Util::TypeConstraints';
78
79             # and if it is from Moose then undef the slot
80             delete ${$class . '::'}{$name};
81         }
82     }
83 }
84
85 ## --------------------------------------------------------
86 ## type registry and some useful functions for it
87 ## --------------------------------------------------------
88
89 my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
90
91 sub get_type_constraint_registry         { $REGISTRY }
92 sub list_all_type_constraints            { keys %{$REGISTRY->type_constraints} }
93 sub export_type_constraints_as_functions {
94     my $pkg = caller();
95     no strict 'refs';
96     foreach my $constraint (keys %{$REGISTRY->type_constraints}) {
97         *{"${pkg}::${constraint}"} = $REGISTRY->get_type_constraint($constraint)
98                                               ->_compiled_type_constraint;
99     }
100 }
101
102 sub create_type_constraint_union (@) {
103     my @type_constraint_names;
104
105     if (scalar @_ == 1 && _detect_type_constraint_union($_[0])) {
106         @type_constraint_names = _parse_type_constraint_union($_[0]);
107     }
108     else {
109         @type_constraint_names = @_;
110     }
111
112     (scalar @type_constraint_names >= 2)
113         || confess "You must pass in at least 2 type names to make a union";
114
115     ($REGISTRY->has_type_constraint($_))
116         || confess "Could not locate type constraint ($_) for the union"
117             foreach @type_constraint_names;
118
119     return Moose::Meta::TypeConstraint::Union->new(
120         type_constraints => [
121             map {
122                 $REGISTRY->get_type_constraint($_)
123             } @type_constraint_names
124         ],
125     );
126 }
127
128 sub create_parameterized_type_constraint ($) {
129     my $type_constraint_name = shift;
130
131     my ($base_type, $type_parameter) = _parse_parameterized_type_constraint($type_constraint_name);
132
133     (defined $base_type && defined $type_parameter)
134         || confess "Could not parse type name ($type_constraint_name) correctly";
135
136     ($REGISTRY->has_type_constraint($base_type))
137         || confess "Could not locate the base type ($base_type)";
138
139     return Moose::Meta::TypeConstraint::Parameterized->new(
140         name           => $type_constraint_name,
141         parent         => $REGISTRY->get_type_constraint($base_type),
142         type_parameter => find_or_create_type_constraint(
143             $type_parameter => {
144                 parent     => $REGISTRY->get_type_constraint('Object'),
145                 constraint => sub { $_[0]->isa($type_parameter) }
146             }
147         ),
148     );
149 }
150
151 sub find_or_create_type_constraint ($;$) {
152     my ($type_constraint_name, $options_for_anon_type) = @_;
153
154     return $REGISTRY->get_type_constraint($type_constraint_name)
155         if $REGISTRY->has_type_constraint($type_constraint_name);
156
157     my $constraint;
158
159     if (_detect_type_constraint_union($type_constraint_name)) {
160         $constraint = create_type_constraint_union($type_constraint_name);
161     }
162     elsif (_detect_parameterized_type_constraint($type_constraint_name)) {
163         $constraint = create_parameterized_type_constraint($type_constraint_name);
164     }
165     else {
166         # NOTE:
167         # if there is no $options_for_anon_type 
168         # specified, then we assume they don't 
169         # want to create one, and return nothing.
170         return unless defined $options_for_anon_type;        
171
172         # NOTE:
173         # otherwise assume that we should create
174         # an ANON type with the $options_for_anon_type
175         # options which can be passed in. It should
176         # be noted that these don't get registered
177         # so we need to return it.
178         # - SL
179         return Moose::Meta::TypeConstraint->new(
180             name => '__ANON__',
181             %{$options_for_anon_type}
182         );
183     }
184
185     $REGISTRY->add_type_constraint($constraint);
186     return $constraint;
187 }
188
189 ## --------------------------------------------------------
190 ## exported functions ...
191 ## --------------------------------------------------------
192
193 sub find_type_constraint ($) { $REGISTRY->get_type_constraint(@_) }
194
195 # type constructors
196
197 sub type ($$;$$) {
198     splice(@_, 1, 0, undef);
199     goto &_create_type_constraint;
200 }
201
202 sub subtype ($$;$$$) {
203     # NOTE:
204     # this adds an undef for the name
205     # if this is an anon-subtype:
206     #   subtype(Num => where { $_ % 2 == 0 }) # anon 'even' subtype
207     # but if the last arg is not a code
208     # ref then it is a subtype alias:
209     #   subtype(MyNumbers => as Num); # now MyNumbers is the same as Num
210     # ... yeah I know it's ugly code
211     # - SL
212     unshift @_ => undef if scalar @_ <= 2 && (reftype($_[1]) || '') eq 'CODE';
213     goto &_create_type_constraint;
214 }
215
216 sub coerce ($@) {
217     my ($type_name, @coercion_map) = @_;
218     _install_type_coercions($type_name, \@coercion_map);
219 }
220
221 sub as      ($) { $_[0] }
222 sub from    ($) { $_[0] }
223 sub where   (&) { $_[0] }
224 sub via     (&) { $_[0] }
225
226 sub message     (&) { +{ message   => $_[0] } }
227 sub optimize_as (&) { +{ optimized => $_[0] } }
228
229 sub enum ($;@) {
230     my ($type_name, @values) = @_;
231     (scalar @values >= 2)
232         || confess "You must have at least two values to enumerate through";
233     my %valid = map { $_ => 1 } @values;
234     _create_type_constraint(
235         $type_name,
236         'Str',
237         sub { $valid{$_} }
238     );
239 }
240
241 ## --------------------------------------------------------
242 ## desugaring functions ...
243 ## --------------------------------------------------------
244
245 sub _create_type_constraint ($$$;$$) {
246     my $name   = shift;
247     my $parent = shift;
248     my $check  = shift;
249
250     my ($message, $optimized);
251     for (@_) {
252         $message   = $_->{message}   if exists $_->{message};
253         $optimized = $_->{optimized} if exists $_->{optimized};
254     }
255
256     my $pkg_defined_in = scalar(caller(0));
257
258     if (defined $name) {
259         my $type = $REGISTRY->get_type_constraint($name);
260
261         ($type->_package_defined_in eq $pkg_defined_in)
262             || confess ("The type constraint '$name' has already been created in "
263                        . $type->_package_defined_in . " and cannot be created again in "
264                        . $pkg_defined_in)
265                  if defined $type;
266     }
267
268     $parent = find_or_create_type_constraint($parent) if defined $parent;
269     
270     my $constraint = Moose::Meta::TypeConstraint->new(
271         name               => $name || '__ANON__',
272         package_defined_in => $pkg_defined_in,
273
274         ($parent    ? (parent     => $parent )   : ()),
275         ($check     ? (constraint => $check)     : ()),
276         ($message   ? (message    => $message)   : ()),
277         ($optimized ? (optimized  => $optimized) : ()),
278     );
279     
280     # NOTE:
281     # if we have a type constraint union, and no 
282     # type check, this means we are just aliasing
283     # the union constraint, which means we need to 
284     # handle this differently.
285     # - SL
286     if (not(defined $check) 
287         && $parent->isa('Moose::Meta::TypeConstraint::Union') 
288         && $parent->has_coercion 
289         ){
290         $constraint->coercion(Moose::Meta::TypeCoercion::Union->new(
291             type_constraint => $parent
292         ));
293     }    
294
295     $REGISTRY->add_type_constraint($constraint)
296         if defined $name;
297
298     return $constraint;
299 }
300
301 sub _install_type_coercions ($$) {
302     my ($type_name, $coercion_map) = @_;
303     my $type = $REGISTRY->get_type_constraint($type_name);
304     (defined $type)
305         || confess "Cannot find type '$type_name', perhaps you forgot to load it.";
306     if ($type->has_coercion) {
307         $type->coercion->add_type_coercions(@$coercion_map);
308     }
309     else {
310         my $type_coercion = Moose::Meta::TypeCoercion->new(
311             type_coercion_map => $coercion_map,
312             type_constraint   => $type
313         );
314         $type->coercion($type_coercion);
315     }
316 }
317
318 ## --------------------------------------------------------
319 ## type notation parsing ...
320 ## --------------------------------------------------------
321
322 {
323     # All I have to say is mugwump++ cause I know
324     # do not even have enough regexp-fu to be able
325     # to have written this (I can only barely
326     # understand it as it is)
327     # - SL
328
329     use re "eval";
330
331     my $valid_chars = qr{[\w:]};
332     my $type_atom   = qr{ $valid_chars+ };
333
334     my $type                = qr{  $valid_chars+  (?: \[  (??{$any})  \] )? }x;
335     my $type_capture_parts  = qr{ ($valid_chars+) (?: \[ ((??{$any})) \] )? }x;
336     my $type_with_parameter = qr{  $valid_chars+      \[  (??{$any})  \]    }x;
337
338     my $op_union = qr{ \s* \| \s* }x;
339     my $union    = qr{ $type (?: $op_union $type )+ }x;
340
341     our $any = qr{ $type | $union }x;
342
343     sub _parse_parameterized_type_constraint {
344         $_[0] =~ m{ $type_capture_parts }x;
345         return ($1, $2);
346     }
347
348     sub _detect_parameterized_type_constraint {
349         $_[0] =~ m{ ^ $type_with_parameter $ }x;
350     }
351
352     sub _parse_type_constraint_union {
353         my $given = shift;
354         my @rv;
355         while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
356                 push @rv => $1;
357         }
358         (pos($given) eq length($given))
359             || confess "'$given' didn't parse (parse-pos="
360                      . pos($given)
361                      . " and str-length="
362                      . length($given)
363                      . ")";
364         @rv;
365     }
366
367     sub _detect_type_constraint_union {
368         $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
369     }
370 }
371
372 ## --------------------------------------------------------
373 # define some basic built-in types
374 ## --------------------------------------------------------
375
376 type 'Any'  => where { 1 }; # meta-type including all
377 type 'Item' => where { 1 }; # base-type
378
379 subtype 'Undef'   => as 'Item' => where { !defined($_) };
380 subtype 'Defined' => as 'Item' => where {  defined($_) };
381
382 subtype 'Bool'
383     => as 'Item'
384     => where { !defined($_) || $_ eq "" || "$_" eq '1' || "$_" eq '0' };
385
386 subtype 'Value'
387     => as 'Defined'
388     => where { !ref($_) }
389     => optimize_as { defined($_[0]) && !ref($_[0]) };
390
391 subtype 'Ref'
392     => as 'Defined'
393     => where {  ref($_) }
394     => optimize_as { ref($_[0]) };
395
396 subtype 'Str'
397     => as 'Value'
398     => where { 1 }
399     => optimize_as { defined($_[0]) && !ref($_[0]) };
400
401 subtype 'Num'
402     => as 'Value'
403     => where { Scalar::Util::looks_like_number($_) }
404     => optimize_as { !ref($_[0]) && Scalar::Util::looks_like_number($_[0]) };
405
406 subtype 'Int'
407     => as 'Num'
408     => where { "$_" =~ /^-?[0-9]+$/ }
409     => optimize_as { defined($_[0]) && !ref($_[0]) && $_[0] =~ /^-?[0-9]+$/ };
410
411 subtype 'ScalarRef' => as 'Ref' => where { ref($_) eq 'SCALAR' } => optimize_as { ref($_[0]) eq 'SCALAR' };
412 subtype 'ArrayRef'  => as 'Ref' => where { ref($_) eq 'ARRAY'  } => optimize_as { ref($_[0]) eq 'ARRAY'  };
413 subtype 'HashRef'   => as 'Ref' => where { ref($_) eq 'HASH'   } => optimize_as { ref($_[0]) eq 'HASH'   };
414 subtype 'CodeRef'   => as 'Ref' => where { ref($_) eq 'CODE'   } => optimize_as { ref($_[0]) eq 'CODE'   };
415 subtype 'RegexpRef' => as 'Ref' => where { ref($_) eq 'Regexp' } => optimize_as { ref($_[0]) eq 'Regexp' };
416 subtype 'GlobRef'   => as 'Ref' => where { ref($_) eq 'GLOB'   } => optimize_as { ref($_[0]) eq 'GLOB'   };
417
418 # NOTE:
419 # scalar filehandles are GLOB refs,
420 # but a GLOB ref is not always a filehandle
421 subtype 'FileHandle'
422     => as 'GlobRef'
423     => where { Scalar::Util::openhandle($_) }
424     => optimize_as { ref($_[0]) eq 'GLOB' && Scalar::Util::openhandle($_[0]) };
425
426 # NOTE:
427 # blessed(qr/.../) returns true,.. how odd
428 subtype 'Object'
429     => as 'Ref'
430     => where { blessed($_) && blessed($_) ne 'Regexp' }
431     => optimize_as { blessed($_[0]) && blessed($_[0]) ne 'Regexp' };
432
433 subtype 'Role'
434     => as 'Object'
435     => where { $_->can('does') }
436     => optimize_as { blessed($_[0]) && $_[0]->can('does') };
437
438 my $_class_name_checker = sub {
439     return if ref($_[0]);
440     return unless defined($_[0]) && length($_[0]);
441
442     # walk the symbol table tree to avoid autovififying
443     # \*{${main::}{"Foo::"}} == \*main::Foo::
444
445     my $pack = \*::;
446     foreach my $part (split('::', $_[0])) {
447         return unless exists ${$$pack}{"${part}::"};
448         $pack = \*{${$$pack}{"${part}::"}};
449     }
450
451     # check for $VERSION or @ISA
452     return 1 if exists ${$$pack}{VERSION}
453              && defined *{${$$pack}{VERSION}}{SCALAR};
454     return 1 if exists ${$$pack}{ISA}
455              && defined *{${$$pack}{ISA}}{ARRAY};
456
457     # check for any method
458     foreach ( keys %{$$pack} ) {
459         next if substr($_, -2, 2) eq '::';
460         return 1 if defined *{${$$pack}{$_}}{CODE};
461     }
462
463     # fail
464     return;
465 };
466
467 subtype 'ClassName'
468     => as 'Str'
469     => $_class_name_checker # where ...
470     => { optimize => $_class_name_checker };
471
472 ## --------------------------------------------------------
473 # end of built-in types ...
474 ## --------------------------------------------------------
475
476 {
477     my @BUILTINS = list_all_type_constraints();
478     sub list_all_builtin_type_constraints { @BUILTINS }
479 }
480
481 1;
482
483 __END__
484
485 =pod
486
487 =head1 NAME
488
489 Moose::Util::TypeConstraints - Type constraint system for Moose
490
491 =head1 SYNOPSIS
492
493   use Moose::Util::TypeConstraints;
494
495   type 'Num' => where { Scalar::Util::looks_like_number($_) };
496
497   subtype 'Natural'
498       => as 'Num'
499       => where { $_ > 0 };
500
501   subtype 'NaturalLessThanTen'
502       => as 'Natural'
503       => where { $_ < 10 }
504       => message { "This number ($_) is not less than ten!" };
505
506   coerce 'Num'
507       => from 'Str'
508         => via { 0+$_ };
509
510   enum 'RGBColors' => qw(red green blue);
511
512 =head1 DESCRIPTION
513
514 This module provides Moose with the ability to create custom type
515 contraints to be used in attribute definition.
516
517 =head2 Important Caveat
518
519 This is B<NOT> a type system for Perl 5. These are type constraints,
520 and they are not used by Moose unless you tell it to. No type
521 inference is performed, expression are not typed, etc. etc. etc.
522
523 This is simply a means of creating small constraint functions which
524 can be used to simplify your own type-checking code.
525
526 =head2 Slightly Less Important Caveat
527
528 It is almost always a good idea to quote your type and subtype names.
529 This is to prevent perl from trying to execute the call as an indirect
530 object call. This issue only seems to come up when you have a subtype
531 the same name as a valid class, but when the issue does arise it tends
532 to be quite annoying to debug.
533
534 So for instance, this:
535
536   subtype DateTime => as Object => where { $_->isa('DateTime') };
537
538 will I<Just Work>, while this:
539
540   use DateTime;
541   subtype DateTime => as Object => where { $_->isa('DateTime') };
542
543 will fail silently and cause many headaches. The simple way to solve
544 this, as well as future proof your subtypes from classes which have
545 yet to have been created yet, is to simply do this:
546
547   use DateTime;
548   subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') };
549
550 =head2 Default Type Constraints
551
552 This module also provides a simple hierarchy for Perl 5 types, this
553 could probably use some work, but it works for me at the moment.
554
555   Any
556   Item
557       Bool
558       Undef
559       Defined
560           Value
561               Num
562                 Int
563               Str
564                 ClassName
565           Ref
566               ScalarRef
567               ArrayRef
568               HashRef
569               CodeRef
570               RegexpRef
571               GlobRef
572                 FileHandle
573               Object
574                   Role
575
576 Suggestions for improvement are welcome.
577
578 B<NOTE:> The C<Undef> type constraint does not work correctly
579 in every occasion, please use it sparringly.
580
581 B<NOTE:> The C<ClassName> type constraint is simply a subtype
582 of string which responds true to C<isa('UNIVERSAL')>. This means
583 that your class B<must> be loaded for this type constraint to
584 pass. I know this is not ideal for all, but it is a saner
585 restriction than most others.
586
587 =head2 Use with Other Constraint Modules
588
589 This module should play fairly nicely with other constraint
590 modules with only some slight tweaking. The C<where> clause
591 in types is expected to be a C<CODE> reference which checks
592 it's first argument and returns a bool. Since most constraint
593 modules work in a similar way, it should be simple to adapt
594 them to work with Moose.
595
596 For instance, this is how you could use it with
597 L<Declare::Constraints::Simple> to declare a completely new type.
598
599   type 'HashOfArrayOfObjects'
600       => IsHashRef(
601           -keys   => HasLength,
602           -values => IsArrayRef( IsObject ));
603
604 For more examples see the F<t/204_example_w_DCS.t> test file.
605
606 Here is an example of using L<Test::Deep> and it's non-test
607 related C<eq_deeply> function.
608
609   type 'ArrayOfHashOfBarsAndRandomNumbers'
610       => where {
611           eq_deeply($_,
612               array_each(subhashof({
613                   bar           => isa('Bar'),
614                   random_number => ignore()
615               })))
616         };
617
618 For a complete example see the F<t/205_example_w_TestDeep.t>
619 test file.
620
621 =head1 FUNCTIONS
622
623 =head2 Type Constraint Construction & Locating
624
625 =over 4
626
627 =item B<create_type_constraint_union ($pipe_seperated_types | @type_constraint_names)>
628
629 Given string with C<$pipe_seperated_types> or a list of C<@type_constraint_names>,
630 this will return a L<Moose::Meta::TypeConstraint::Union> instance.
631
632 =item B<create_parameterized_type_constraint ($type_name)>
633
634 Given a C<$type_name> in the form of:
635
636   BaseType[ContainerType]
637
638 this will extract the base type and container type and build an instance of
639 L<Moose::Meta::TypeConstraint::Parameterized> for it.
640
641 =item B<find_or_create_type_constraint ($type_name, ?$options_for_anon_type)>
642
643 This will attempt to find or create a type constraint given the a C<$type_name>.
644 If it cannot find it in the registry, it will see if it should be a union or
645 container type an create one if appropriate, and lastly if nothing can be
646 found or created that way, it will create an anon-type using the
647 C<$options_for_anon_type> HASH ref to populate it. If the C<$options_for_anon_type>
648 is not specified (it is C<undef>), then it will not create anything and simply
649 return.
650
651 =item B<find_type_constraint ($type_name)>
652
653 This function can be used to locate a specific type constraint
654 meta-object, of the class L<Moose::Meta::TypeConstraint> or a
655 derivative. What you do with it from there is up to you :)
656
657 =item B<get_type_constraint_registry>
658
659 Fetch the L<Moose::Meta::TypeConstraint::Registry> object which
660 keeps track of all type constraints.
661
662 =item B<list_all_type_constraints>
663
664 This will return a list of type constraint names, you can then
665 fetch them using C<find_type_constraint ($type_name)> if you
666 want to.
667
668 =item B<list_all_builtin_type_constraints>
669
670 This will return a list of builtin type constraints, meaning,
671 those which are defined in this module. See the section
672 labeled L<Default Type Constraints> for a complete list.
673
674 =item B<export_type_constraints_as_functions>
675
676 This will export all the current type constraints as functions
677 into the caller's namespace. Right now, this is mostly used for
678 testing, but it might prove useful to others.
679
680 =back
681
682 =head2 Type Constraint Constructors
683
684 The following functions are used to create type constraints.
685 They will then register the type constraints in a global store
686 where Moose can get to them if it needs to.
687
688 See the L<SYNOPSIS> for an example of how to use these.
689
690 =over 4
691
692 =item B<type ($name, $where_clause)>
693
694 This creates a base type, which has no parent.
695
696 =item B<subtype ($name, $parent, $where_clause, ?$message)>
697
698 This creates a named subtype.
699
700 =item B<subtype ($parent, $where_clause, ?$message)>
701
702 This creates an unnamed subtype and will return the type
703 constraint meta-object, which will be an instance of
704 L<Moose::Meta::TypeConstraint>.
705
706 =item B<enum ($name, @values)>
707
708 This will create a basic subtype for a given set of strings.
709 The resulting constraint will be a subtype of C<Str> and
710 will match any of the items in C<@values>. It is case sensitive.
711 See the L<SYNOPSIS> for a simple example.
712
713 B<NOTE:> This is not a true proper enum type, it is simple
714 a convient constraint builder.
715
716 =item B<as>
717
718 This is just sugar for the type constraint construction syntax.
719
720 =item B<where>
721
722 This is just sugar for the type constraint construction syntax.
723
724 =item B<message>
725
726 This is just sugar for the type constraint construction syntax.
727
728 =item B<optimize_as>
729
730 This can be used to define a "hand optimized" version of your
731 type constraint which can be used to avoid traversing a subtype
732 constraint heirarchy.
733
734 B<NOTE:> You should only use this if you know what you are doing,
735 all the built in types use this, so your subtypes (assuming they
736 are shallow) will not likely need to use this.
737
738 =back
739
740 =head2 Type Coercion Constructors
741
742 Type constraints can also contain type coercions as well. If you
743 ask your accessor to coerce, then Moose will run the type-coercion
744 code first, followed by the type constraint check. This feature
745 should be used carefully as it is very powerful and could easily
746 take off a limb if you are not careful.
747
748 See the L<SYNOPSIS> for an example of how to use these.
749
750 =over 4
751
752 =item B<coerce>
753
754 =item B<from>
755
756 This is just sugar for the type coercion construction syntax.
757
758 =item B<via>
759
760 This is just sugar for the type coercion construction syntax.
761
762 =back
763
764 =head2 Namespace Management
765
766 =over 4
767
768 =item B<unimport>
769
770 This will remove all the type constraint keywords from the
771 calling class namespace.
772
773 =back
774
775 =head1 BUGS
776
777 All complex software has bugs lurking in it, and this module is no
778 exception. If you find a bug please either email me, or add the bug
779 to cpan-RT.
780
781 =head1 AUTHOR
782
783 Stevan Little E<lt>stevan@iinteractive.comE<gt>
784
785 =head1 COPYRIGHT AND LICENSE
786
787 Copyright 2006, 2007 by Infinity Interactive, Inc.
788
789 L<http://www.iinteractive.com>
790
791 This library is free software; you can redistribute it and/or modify
792 it under the same terms as Perl itself.
793
794 =cut