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