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