0791eda6c8989d8689273c87ef99b8819596661a
[gitmo/MooseX-Types.git] / lib / MooseX / Types.pm
1 package MooseX::Types;
2 use Moose;
3
4 =head1 NAME
5
6 MooseX::Types - Organise your Moose types in libraries
7
8 =cut
9
10 #use warnings;
11 #use strict;
12
13 use Moose::Util::TypeConstraints;
14 use MooseX::Types::TypeDecorator;
15 use MooseX::Types::Base             ();
16 use MooseX::Types::Util             qw( filter_tags );
17 use MooseX::Types::UndefinedType;
18 use Carp::Clan                      qw( ^MooseX::Types );
19
20 use namespace::clean -except => [qw( meta )];
21
22 our $VERSION = 0.06;
23 my $UndefMsg = q{Action for type '%s' not yet defined in library '%s'};
24
25 =head1 SYNOPSIS
26
27 =head2 Library Definition
28
29   package MyLibrary;
30
31   # predeclare our own types
32   use MooseX::Types 
33     -declare => [qw(
34         PositiveInt NegativeInt
35         ArrayRefOfPositiveInt ArrayRefOfAtLeastThreeNegativeInts
36         LotsOfInnerConstraints StrOrArrayRef
37     )];
38
39   # import builtin types
40   use MooseX::Types::Moose 'Int';
41
42   # type definition
43   subtype PositiveInt, 
44       as Int, 
45       where { $_ > 0 },
46       message { "Int is not larger than 0" };
47   
48   subtype NegativeInt,
49       as Int,
50       where { $_ < 0 },
51       message { "Int is not smaller than 0" };
52
53   # type coercion
54   coerce PositiveInt,
55       from Int,
56           via { 1 };
57
58   # with parameterized constraints.
59   
60   subtype ArrayRefOfPositiveInt,
61     as ArrayRef[PositiveInt];
62     
63   subtype ArrayRefOfAtLeastThreeNegativeInts,
64     as ArrayRef[NegativeInt],
65     where { scalar(@$_) > 2 };
66
67   subtype LotsOfInnerConstraints,
68     as ArrayRef[ArrayRef[HashRef[Int]]];
69     
70   # with TypeConstraint Unions
71   
72   subtype StrOrArrayRef,
73     as Str|ArrayRef;
74
75   1;
76
77 =head2 Usage
78
79   package Foo;
80   use Moose;
81   use MyLibrary qw( PositiveInt NegativeInt );
82
83   # use the exported constants as type names
84   has 'bar',
85       isa    => PositiveInt,
86       is     => 'rw';
87   has 'baz',
88       isa    => NegativeInt,
89       is     => 'rw';
90
91   sub quux {
92       my ($self, $value);
93
94       # test the value
95       print "positive\n" if is_PositiveInt($value);
96       print "negative\n" if is_NegativeInt($value);
97
98       # coerce the value, NegativeInt doesn't have a coercion
99       # helper, since it didn't define any coercions.
100       $value = to_PositiveInt($value) or die "Cannot coerce";
101   }
102
103   1;
104
105 =head1 DESCRIPTION
106
107 The types provided with L<Moose> are by design global. This package helps
108 you to organise and selectively import your own and the built-in types in
109 libraries. As a nice side effect, it catches typos at compile-time too.
110
111 However, the main reason for this module is to provide an easy way to not
112 have conflicts with your type names, since the internal fully qualified
113 names of the types will be prefixed with the library's name.
114
115 This module will also provide you with some helper functions to make it 
116 easier to use Moose types in your code.
117
118 =head1 TYPE HANDLER FUNCTIONS
119
120 =head2 $type
121
122 A constant with the name of your type. It contains the type's fully
123 qualified name. Takes no value, as all constants.
124
125 =head2 is_$type
126
127 This handler takes a value and tests if it is a valid value for this
128 C<$type>. It will return true or false.
129
130 =head2 to_$type
131
132 A handler that will take a value and coerce it into the C<$type>. It will
133 return a false value if the type could not be coerced.
134
135 B<Important Note>: This handler will only be exported for types that can
136 do type coercion. This has the advantage that a coercion to a type that
137 cannot hasn't defined any coercions will lead to a compile-time error.
138
139 =head1 LIBRARY DEFINITION
140
141 A MooseX::Types is just a normal Perl module. Unlike Moose 
142 itself, it does not install C<use strict> and C<use warnings> in your
143 class by default, so this is up to you.
144
145 The only thing a library is required to do is
146
147   use MooseX::Types -declare => \@types;
148
149 with C<@types> being a list of types you wish to define in this library.
150 This line will install a proper base class in your package as well as the
151 full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared 
152 types. It will then hand control over to L<Moose::Util::TypeConstraints>'
153 C<import> method to export the functions you will need to declare your
154 types.
155
156 If you want to use Moose' built-in types (e.g. for subtyping) you will 
157 want to 
158
159   use MooseX::Types::Moose @types;
160
161 to import the helpers from the shipped L<MooseX::Types::Moose>
162 library which can export all types that come with Moose.
163
164 You will have to define coercions for your types or your library won't
165 export a L</to_$type> coercion helper for it.
166
167 Note that you currently cannot define types containing C<::>, since 
168 exporting would be a problem.
169
170 You also don't need to use C<warnings> and C<strict>, since the
171 definition of a library automatically exports those.
172
173 =head1 LIBRARY USAGE
174
175 You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a
176 library by C<use>ing it with a list of types to import as arguments. If
177 you want all of them, use the C<:all> tag. For example:
178
179   use MyLibrary      ':all';
180   use MyOtherLibrary qw( TypeA TypeB );
181
182 MooseX::Types comes with a library of Moose' built-in types called
183 L<MooseX::Types::Moose>.
184
185 The exporting mechanism is, since version 0.5, implemented via a wrapper
186 around L<Sub::Exporter>. This means you can do something like this:
187
188   use MyLibrary TypeA => { -as => 'MyTypeA' },
189                 TypeB => { -as => 'MyTypeB' };
190
191 =head1 WRAPPING A LIBRARY
192
193 You can define your own wrapper subclasses to manipulate the behaviour
194 of a set of library exports. Here is an example:
195
196   package MyWrapper;
197   use strict;
198   use Class::C3;
199   use base 'MooseX::Types::Wrapper';
200
201   sub coercion_export_generator {
202       my $class = shift;
203       my $code = $class->next::method(@_);
204       return sub {
205           my $value = $code->(@_);
206           warn "Coercion returned undef!"
207               unless defined $value;
208           return $value;
209       };
210   }
211
212   1;
213
214 This class wraps the coercion generator (e.g., C<to_Int()>) and warns
215 if a coercion returned an undefined value. You can wrap any library
216 with this:
217
218   package Foo;
219   use strict;
220   use MyWrapper MyLibrary => [qw( Foo Bar )],
221                 Moose     => [qw( Str Int )];
222
223   ...
224   1;
225
226 The C<Moose> library name is a special shortcut for 
227 L<MooseX::Types::Moose>.
228
229 =head2 Generator methods you can overload
230
231 =over 4
232
233 =item type_export_generator( $short, $full )
234
235 Creates a closure returning the type's L<Moose::Meta::TypeConstraint> 
236 object. 
237
238 =item check_export_generator( $short, $full, $undef_message )
239
240 This creates the closure used to test if a value is valid for this type.
241
242 =item coercion_export_generator( $short, $full, $undef_message )
243
244 This is the closure that's doing coercions.
245
246 =back
247
248 =head2 Provided Parameters
249
250 =over 4
251
252 =item $short
253
254 The short, exported name of the type.
255
256 =item $full
257
258 The fully qualified name of this type as L<Moose> knows it.
259
260 =item $undef_message
261
262 A message that will be thrown when type functionality is used but the
263 type does not yet exist.
264
265 =head1 NOTES REGARDING TYPE UNIONS
266
267 L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
268 which generally allows you to easily create union types:
269
270   subtype StrOrArrayRef,
271     as Str|ArrayRef;    
272
273 As with parameterized constrains, this overloading extends to modules using the
274 types you define in a type library.
275
276     use Moose;
277     use MooseX::Types::Moose qw(HashRef Int);
278     
279     has 'attr' => (isa=>HashRef|Int);
280
281 And everything should just work as you'd think.
282     
283 =head1 METHODS
284
285 =head2 import
286
287 Installs the L<MooseX::Types::Base> class into the caller and 
288 exports types according to the specification described in 
289 L</"LIBRARY DEFINITION">. This will continue to 
290 L<Moose::Util::TypeConstraints>' C<import> method to export helper
291 functions you will need to declare your types.
292
293 =cut
294
295 sub import {
296     my ($class, %args) = @_;
297     my  $callee = caller;
298
299     # everyone should want this
300     strict->import;
301     warnings->import;
302
303     # inject base class into new library
304     {   no strict 'refs';
305         unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
306     }
307
308     # generate predeclared type helpers
309     if (my @orig_declare = @{ $args{ -declare } || [] }) {
310         my ($tags, $declare) = filter_tags @orig_declare;
311         my @to_export;
312
313         for my $type (@$declare) {
314
315             croak "Cannot create a type containing '::' ($type) at the moment"
316                 if $type =~ /::/;
317
318             # add type to library and remember to export
319             $callee->add_type($type);
320             push @to_export, $type;
321         }
322
323         $callee->import({ -full => 1, -into => $callee }, @to_export);
324     }
325
326     # run type constraints import
327     return Moose::Util::TypeConstraints->import({ into => $callee });
328 }
329
330 =head2 type_export_generator
331
332 Generate a type export, e.g. C<Int()>. This will return either a
333 L<Moose::Meta::TypeConstraint> object, or alternatively a
334 L<MooseX::Types::UndefinedType> object if the type was not
335 yet defined.
336
337 =cut
338
339 sub type_export_generator {
340     my ($class, $type, $name) = @_;
341     
342     ## Return an anonymous subroutine that will generate the proxied type
343     ## constraint for you.
344     
345     return sub {
346         my $type_constraint;
347         if(defined(my $params = shift @_)) {
348             ## We currently only allow a TC to accept a single, ArrayRef
349             ## parameter, as in HashRef[Int], where [Int] is what's inside the
350             ## ArrayRef passed.
351             if(ref $params eq 'ARRAY') {
352                 $type_constraint = $class->create_arged_type_constraint($name, @$params);
353             } else {
354                 croak 'Arguments must be an ArrayRef, not '. ref $params;
355             }
356         } else {
357             $type_constraint = $class->create_base_type_constraint($name);
358         }
359         $type_constraint = defined($type_constraint) ? $type_constraint
360          : MooseX::Types::UndefinedType->new($name);
361          
362         my $type_decorator = $class->create_type_decorator($type_constraint);
363         
364         ## If there are additional args, that means it's probably stuff that
365         ## needs to be returned to the subtype.  Not an ideal solution here but
366         ## doesn't seem to cause trouble.
367         
368         if(@_) {
369             return ($type_decorator, @_);
370         } else {
371             return $type_decorator;
372         }
373     };
374 }
375
376 =head2 create_arged_type_constraint ($name, @args)
377
378 Given a String $name with @args find the matching typeconstraint and parameterize
379 it with @args.
380
381 =cut
382
383 sub create_arged_type_constraint {
384     my ($class, $name, @args) = @_;  
385     my $type_constraint = Moose::Util::TypeConstraints::find_or_create_type_constraint("$name");
386         return $type_constraint->parameterize(@args);
387 }
388
389 =head2 create_base_type_constraint ($name)
390
391 Given a String $name, find the matching typeconstraint.
392
393 =cut
394
395 sub create_base_type_constraint {
396     my ($class, $name) = @_;
397     return find_type_constraint($name);
398 }
399
400 =head2 create_type_decorator ($type_constraint)
401
402 Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator>
403 instance.
404
405 =cut
406
407 sub create_type_decorator {
408     my ($class, $type_constraint) = @_;
409     return MooseX::Types::TypeDecorator->new($type_constraint);
410 }
411
412 =head2 coercion_export_generator
413
414 This generates a coercion handler function, e.g. C<to_Int($value)>. 
415
416 =cut
417
418 sub coercion_export_generator {
419     my ($class, $type, $full, $undef_msg) = @_;
420     return sub {
421         my ($value) = @_;
422
423         # we need a type object
424         my $tobj = find_type_constraint($full) or croak $undef_msg;
425         my $return = $tobj->coerce($value);
426
427         # non-successful coercion returns false
428         return unless $tobj->check($return);
429
430         return $return;
431     }
432 }
433
434 =head2 check_export_generator
435
436 Generates a constraint check closure, e.g. C<is_Int($value)>.
437
438 =cut
439
440 sub check_export_generator {
441     my ($class, $type, $full, $undef_msg) = @_;
442     return sub {
443         my ($value) = @_;
444
445         # we need a type object
446         my $tobj = find_type_constraint($full) or croak $undef_msg;
447
448         return $tobj->check($value);
449     }
450 }
451
452 =head1 CAVEATS
453
454 The following are lists of gotcha's and their workarounds for developers coming
455 from the standard string based type constraint names
456
457 =head2 Uniqueness
458
459 A library makes the types quasi-unique by prefixing their names with (by
460 default) the library package name. If you're only using the type handler
461 functions provided by MooseX::Types, you shouldn't ever have to use
462 a type's actual full name.
463
464 =head2 Argument separation ('=>' versus ',')
465
466 The Perlop manpage has this to say about the '=>' operator: "The => operator is
467 a synonym for the comma, but forces any word (consisting entirely of word
468 characters) to its left to be interpreted as a string (as of 5.001). This
469 includes words that might otherwise be considered a constant or function call."
470
471 Due to this stringification, the following will NOT work as you might think:
472
473   subtype StrOrArrayRef => as Str|ArrayRef;
474   
475 The 'StrOrArrayRef' will have it's stringification activated this causes the
476 subtype to not be created.  Since the bareword type constraints are not strings
477 you really should not try to treat them that way.  You will have to use the ','
478 operator instead.  The author's of this package realize that all the L<Moose>
479 documention and examples nearly uniformly use the '=>' version of the comma
480 operator and this could be an issue if you are converting code.
481
482 Patches welcome for discussion.
483     
484 =head1 SEE ALSO
485
486 L<Moose>, 
487 L<Moose::Util::TypeConstraints>, 
488 L<MooseX::Types::Moose>,
489 L<Sub::Exporter>
490
491 =head1 AUTHOR AND COPYRIGHT
492
493 Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
494 the C<#moose> cabal on C<irc.perl.org>.
495
496 Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
497
498 =head1 LICENSE
499
500 This program is free software; you can redistribute it and/or modify
501 it under the same terms as perl itself.
502
503 =cut
504
505 1;