removed parenthesis hackage and updated docs
[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
475bbd1d 22our $VERSION = 0.06;
8af0a70d 23
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
43 # type definition
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
475bbd1d 266=head1 NOTES REGARDING TYPE UNIONS
267
268L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
269which generally allows you to easily create union types:
270
271 subtype StrOrArrayRef,
272 as Str|ArrayRef;
273
274As with parameterized constrains, this overloading extends to modules using the
275types you define in a type library.
276
277 use Moose;
278 use MooseX::Types::Moose qw(HashRef Int);
279
280 has 'attr' => (isa=>HashRef|Int);
281
282And everything should just work as you'd think.
283
8af0a70d 284=head1 METHODS
285
286=head2 import
287
52d358e2 288Installs the L<MooseX::Types::Base> class into the caller and
e211870f 289exports types according to the specification described in
290L</"LIBRARY DEFINITION">. This will continue to
291L<Moose::Util::TypeConstraints>' C<import> method to export helper
292functions you will need to declare your types.
293
8af0a70d 294=cut
295
296sub import {
297 my ($class, %args) = @_;
298 my $callee = caller;
299
559cf3d8 300 # everyone should want this
301 strict->import;
302 warnings->import;
303
8af0a70d 304 # inject base class into new library
305 { no strict 'refs';
52d358e2 306 unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
8af0a70d 307 }
308
309 # generate predeclared type helpers
e211870f 310 if (my @orig_declare = @{ $args{ -declare } || [] }) {
311 my ($tags, $declare) = filter_tags @orig_declare;
16ddefbf 312 my @to_export;
e211870f 313
314 for my $type (@$declare) {
249888e7 315
316 croak "Cannot create a type containing '::' ($type) at the moment"
317 if $type =~ /::/;
318
16ddefbf 319 # add type to library and remember to export
8af0a70d 320 $callee->add_type($type);
16ddefbf 321 push @to_export, $type;
8af0a70d 322 }
16ddefbf 323
324 $callee->import({ -full => 1, -into => $callee }, @to_export);
8af0a70d 325 }
326
327 # run type constraints import
c20dc98b 328 return Moose::Util::TypeConstraints->import({ into => $callee });
8af0a70d 329}
330
331=head2 type_export_generator
332
e211870f 333Generate a type export, e.g. C<Int()>. This will return either a
334L<Moose::Meta::TypeConstraint> object, or alternatively a
52d358e2 335L<MooseX::Types::UndefinedType> object if the type was not
e211870f 336yet defined.
337
8af0a70d 338=cut
339
340sub type_export_generator {
a706b0f2 341 my ($class, $type, $name) = @_;
4c2125a4 342 return sub {
a706b0f2 343 my $type_constraint;
e088dd03 344 if(defined(my $params = shift @_)) {
345 if(ref $params eq 'ARRAY') {
346 $type_constraint = $class->create_arged_type_constraint($name, @$params);
347 } else {
348 croak 'Arguments must be an ArrayRef, not '. ref $params;
349 }
a706b0f2 350 } else {
e088dd03 351 $type_constraint = $class->create_base_type_constraint($name);
352 }
353 $type_constraint = defined($type_constraint) ? $type_constraint
354 : MooseX::Types::UndefinedType->new($name);
475bbd1d 355
d9002a85 356 my $type_decorator = $class->create_type_decorator($type_constraint);
bb5b7b28 357
d9002a85 358 if(@_) {
359 return ($type_decorator, @_);
360 } else {
361 return $type_decorator;
362 }
e211870f 363 };
8af0a70d 364}
365
a706b0f2 366=head2 create_arged_type_constraint ($name, @args)
367
368Given a String $name with @args find the matching typeconstraint.
369
370=cut
371
372sub create_arged_type_constraint {
373 my ($class, $name, @args) = @_;
575e6fc1 374 my $type_constraint = Moose::Util::TypeConstraints::find_or_create_type_constraint($name);
375 return $type_constraint->parameterize(@args)
a706b0f2 376}
377
378=head2 create_base_type_constraint ($name)
379
380Given a String $name, find the matching typeconstraint.
381
382=cut
383
384sub create_base_type_constraint {
385 my ($class, $name) = @_;
386 return find_type_constraint($name);
387}
388
389=head2 create_type_decorator ($type_constraint)
390
391Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator>
392instance.
393
394=cut
395
396sub create_type_decorator {
397 my ($class, $type_constraint) = @_;
475bbd1d 398 return MooseX::Types::TypeDecorator->new($type_constraint);
a706b0f2 399}
400
8af0a70d 401=head2 coercion_export_generator
402
e211870f 403This generates a coercion handler function, e.g. C<to_Int($value)>.
404
8af0a70d 405=cut
406
407sub coercion_export_generator {
408 my ($class, $type, $full, $undef_msg) = @_;
409 return sub {
410 my ($value) = @_;
411
412 # we need a type object
413 my $tobj = find_type_constraint($full) or croak $undef_msg;
414 my $return = $tobj->coerce($value);
415
416 # non-successful coercion returns false
417 return unless $tobj->check($return);
418
419 return $return;
420 }
421}
422
423=head2 check_export_generator
424
e211870f 425Generates a constraint check closure, e.g. C<is_Int($value)>.
426
8af0a70d 427=cut
428
429sub check_export_generator {
430 my ($class, $type, $full, $undef_msg) = @_;
431 return sub {
432 my ($value) = @_;
433
434 # we need a type object
435 my $tobj = find_type_constraint($full) or croak $undef_msg;
436
437 return $tobj->check($value);
438 }
439}
440
e211870f 441=head1 CAVEATS
442
443A library makes the types quasi-unique by prefixing their names with (by
444default) the library package name. If you're only using the type handler
52d358e2 445functions provided by MooseX::Types, you shouldn't ever have to use
e211870f 446a type's actual full name.
447
8af0a70d 448=head1 SEE ALSO
449
16ddefbf 450L<Moose>,
451L<Moose::Util::TypeConstraints>,
452L<MooseX::Types::Moose>,
453L<Sub::Exporter>
8af0a70d 454
455=head1 AUTHOR AND COPYRIGHT
456
457Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
458the C<#moose> cabal on C<irc.perl.org>.
459
475bbd1d 460Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
461
8af0a70d 462=head1 LICENSE
463
464This program is free software; you can redistribute it and/or modify
465it under the same terms as perl itself.
466
467=cut
468
4691;