incremented version and updated changelog, fixed bug that created extra coercions...
[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
475bbd1d 59 # with parameterized constraints. Please note the containing '(...)'
60
61 subtype ArrayRefOfPositiveInt,
62 as (ArrayRef[PositiveInt]);
63
64 subtype ArrayRefOfAtLeastThreeNegativeInts,
65 as (ArrayRef[NegativeInt]),
66 where { scalar(@$_) > 2 };
67
68 subtype LotsOfInnerConstraints,
69 as (ArrayRef[ArrayRef[HashRef[Int]]]);
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
266=back
267
475bbd1d 268=head1 NOTES REGARDING PARAMETERIZED CONSTRAINTS
269
270L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
271which generally allows you to easily create types with parameters such as:
272
273 subtype ParameterType,
274 as (ArrayRef[Int]);
275
276However, due to an outstanding issue you will need to wrap the parameterized
277type inside parenthesis, as in the example above. Hopefully this limitation
278will be lifted in a future version of this module.
279
280If you are using paramterized types in the options section of an attribute
281declaration, the parenthesis are not needed:
282
283 use Moose;
284 use MooseX::Types::Moose qw(HashRef Int);
285
286 has 'attr' => (isa=>HashRef[Str]);
287
288=head1 NOTES REGARDING TYPE UNIONS
289
290L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading
291which generally allows you to easily create union types:
292
293 subtype StrOrArrayRef,
294 as Str|ArrayRef;
295
296As with parameterized constrains, this overloading extends to modules using the
297types you define in a type library.
298
299 use Moose;
300 use MooseX::Types::Moose qw(HashRef Int);
301
302 has 'attr' => (isa=>HashRef|Int);
303
304And everything should just work as you'd think.
305
8af0a70d 306=head1 METHODS
307
308=head2 import
309
52d358e2 310Installs the L<MooseX::Types::Base> class into the caller and
e211870f 311exports types according to the specification described in
312L</"LIBRARY DEFINITION">. This will continue to
313L<Moose::Util::TypeConstraints>' C<import> method to export helper
314functions you will need to declare your types.
315
8af0a70d 316=cut
317
318sub import {
319 my ($class, %args) = @_;
320 my $callee = caller;
321
559cf3d8 322 # everyone should want this
323 strict->import;
324 warnings->import;
325
8af0a70d 326 # inject base class into new library
327 { no strict 'refs';
52d358e2 328 unshift @{ $callee . '::ISA' }, 'MooseX::Types::Base';
8af0a70d 329 }
330
331 # generate predeclared type helpers
e211870f 332 if (my @orig_declare = @{ $args{ -declare } || [] }) {
333 my ($tags, $declare) = filter_tags @orig_declare;
16ddefbf 334 my @to_export;
e211870f 335
336 for my $type (@$declare) {
249888e7 337
338 croak "Cannot create a type containing '::' ($type) at the moment"
339 if $type =~ /::/;
340
16ddefbf 341 # add type to library and remember to export
8af0a70d 342 $callee->add_type($type);
16ddefbf 343 push @to_export, $type;
8af0a70d 344 }
16ddefbf 345
346 $callee->import({ -full => 1, -into => $callee }, @to_export);
8af0a70d 347 }
348
349 # run type constraints import
c20dc98b 350 return Moose::Util::TypeConstraints->import({ into => $callee });
8af0a70d 351}
352
353=head2 type_export_generator
354
e211870f 355Generate a type export, e.g. C<Int()>. This will return either a
356L<Moose::Meta::TypeConstraint> object, or alternatively a
52d358e2 357L<MooseX::Types::UndefinedType> object if the type was not
e211870f 358yet defined.
359
8af0a70d 360=cut
361
362sub type_export_generator {
a706b0f2 363 my ($class, $type, $name) = @_;
4c2125a4 364 return sub {
a706b0f2 365 my $type_constraint;
e088dd03 366 if(defined(my $params = shift @_)) {
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 }
375 $type_constraint = defined($type_constraint) ? $type_constraint
376 : MooseX::Types::UndefinedType->new($name);
475bbd1d 377
378 return $class->create_type_decorator($type_constraint);
bb5b7b28 379
475bbd1d 380 #if(@_ && wantarray) {
381 # return ($class->create_type_decorator($type_constraint), @_);
382 #} else {
383 # return $class->create_type_decorator($type_constraint);
384 #}
e211870f 385 };
8af0a70d 386}
387
a706b0f2 388=head2 create_arged_type_constraint ($name, @args)
389
390Given a String $name with @args find the matching typeconstraint.
391
392=cut
393
394sub create_arged_type_constraint {
395 my ($class, $name, @args) = @_;
396 ### This whole section is a real TODO :) Ugly hack to get the base tests working.
397 my $fullname = $name."[$args[0]]";
475bbd1d 398
399 #use Data::Dump qw/dump/;
400 #my $tc = Moose::Util::TypeConstraints::find_or_create_type_constraint($name);
401
a706b0f2 402 return Moose::Util::TypeConstraints::create_parameterized_type_constraint($fullname);
403}
404
405=head2 create_base_type_constraint ($name)
406
407Given a String $name, find the matching typeconstraint.
408
409=cut
410
411sub create_base_type_constraint {
412 my ($class, $name) = @_;
413 return find_type_constraint($name);
414}
415
416=head2 create_type_decorator ($type_constraint)
417
418Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator>
419instance.
420
421=cut
422
423sub create_type_decorator {
424 my ($class, $type_constraint) = @_;
475bbd1d 425 return MooseX::Types::TypeDecorator->new($type_constraint);
a706b0f2 426}
427
8af0a70d 428=head2 coercion_export_generator
429
e211870f 430This generates a coercion handler function, e.g. C<to_Int($value)>.
431
8af0a70d 432=cut
433
434sub coercion_export_generator {
435 my ($class, $type, $full, $undef_msg) = @_;
436 return sub {
437 my ($value) = @_;
438
439 # we need a type object
440 my $tobj = find_type_constraint($full) or croak $undef_msg;
441 my $return = $tobj->coerce($value);
442
443 # non-successful coercion returns false
444 return unless $tobj->check($return);
445
446 return $return;
447 }
448}
449
450=head2 check_export_generator
451
e211870f 452Generates a constraint check closure, e.g. C<is_Int($value)>.
453
8af0a70d 454=cut
455
456sub check_export_generator {
457 my ($class, $type, $full, $undef_msg) = @_;
458 return sub {
459 my ($value) = @_;
460
461 # we need a type object
462 my $tobj = find_type_constraint($full) or croak $undef_msg;
463
464 return $tobj->check($value);
465 }
466}
467
e211870f 468=head1 CAVEATS
469
470A library makes the types quasi-unique by prefixing their names with (by
471default) the library package name. If you're only using the type handler
52d358e2 472functions provided by MooseX::Types, you shouldn't ever have to use
e211870f 473a type's actual full name.
474
8af0a70d 475=head1 SEE ALSO
476
16ddefbf 477L<Moose>,
478L<Moose::Util::TypeConstraints>,
479L<MooseX::Types::Moose>,
480L<Sub::Exporter>
8af0a70d 481
482=head1 AUTHOR AND COPYRIGHT
483
484Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to
485the C<#moose> cabal on C<irc.perl.org>.
486
475bbd1d 487Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>.
488
8af0a70d 489=head1 LICENSE
490
491This program is free software; you can redistribute it and/or modify
492it under the same terms as perl itself.
493
494=cut
495
4961;