Commit | Line | Data |
52d358e2 |
1 | package MooseX::Types; |
16ddefbf |
2 | use Moose; |
8af0a70d |
3 | |
4 | =head1 NAME |
5 | |
52d358e2 |
6 | MooseX::Types - Organise your Moose types in libraries |
8af0a70d |
7 | |
8 | =cut |
9 | |
8af0a70d |
10 | use Moose::Util::TypeConstraints; |
4c2125a4 |
11 | use MooseX::Types::TypeDecorator; |
9616cebc |
12 | use MooseX::Types::Base (); |
13 | use MooseX::Types::Util qw( filter_tags ); |
52d358e2 |
14 | use MooseX::Types::UndefinedType; |
16ddefbf |
15 | use Carp::Clan qw( ^MooseX::Types ); |
9616cebc |
16 | |
17 | use namespace::clean -except => [qw( meta )]; |
8af0a70d |
18 | |
eba48805 |
19 | use 5.008; |
e50bf0d9 |
20 | our $VERSION = 0.10; |
8af0a70d |
21 | my $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 | |
105 | The types provided with L<Moose> are by design global. This package helps |
106 | you to organise and selectively import your own and the built-in types in |
107 | libraries. As a nice side effect, it catches typos at compile-time too. |
108 | |
109 | However, the main reason for this module is to provide an easy way to not |
110 | have conflicts with your type names, since the internal fully qualified |
111 | names of the types will be prefixed with the library's name. |
112 | |
113 | This module will also provide you with some helper functions to make it |
114 | easier to use Moose types in your code. |
115 | |
116 | =head1 TYPE HANDLER FUNCTIONS |
117 | |
118 | =head2 $type |
119 | |
120 | A constant with the name of your type. It contains the type's fully |
121 | qualified name. Takes no value, as all constants. |
122 | |
123 | =head2 is_$type |
124 | |
125 | This handler takes a value and tests if it is a valid value for this |
126 | C<$type>. It will return true or false. |
127 | |
128 | =head2 to_$type |
129 | |
130 | A handler that will take a value and coerce it into the C<$type>. It will |
131 | return a false value if the type could not be coerced. |
132 | |
133 | B<Important Note>: This handler will only be exported for types that can |
134 | do type coercion. This has the advantage that a coercion to a type that |
135 | cannot hasn't defined any coercions will lead to a compile-time error. |
136 | |
137 | =head1 LIBRARY DEFINITION |
138 | |
52d358e2 |
139 | A MooseX::Types is just a normal Perl module. Unlike Moose |
8af0a70d |
140 | itself, it does not install C<use strict> and C<use warnings> in your |
141 | class by default, so this is up to you. |
142 | |
143 | The only thing a library is required to do is |
144 | |
52d358e2 |
145 | use MooseX::Types -declare => \@types; |
8af0a70d |
146 | |
147 | with C<@types> being a list of types you wish to define in this library. |
148 | This line will install a proper base class in your package as well as the |
149 | full set of L<handlers|/"TYPE HANDLER FUNCTIONS"> for your declared |
150 | types. It will then hand control over to L<Moose::Util::TypeConstraints>' |
151 | C<import> method to export the functions you will need to declare your |
152 | types. |
153 | |
154 | If you want to use Moose' built-in types (e.g. for subtyping) you will |
155 | want to |
156 | |
52d358e2 |
157 | use MooseX::Types::Moose @types; |
8af0a70d |
158 | |
52d358e2 |
159 | to import the helpers from the shipped L<MooseX::Types::Moose> |
8af0a70d |
160 | library which can export all types that come with Moose. |
161 | |
162 | You will have to define coercions for your types or your library won't |
163 | export a L</to_$type> coercion helper for it. |
164 | |
21a1dfe2 |
165 | Note that you currently cannot define types containing C<::>, since |
249888e7 |
166 | exporting would be a problem. |
167 | |
559cf3d8 |
168 | You also don't need to use C<warnings> and C<strict>, since the |
169 | definition of a library automatically exports those. |
170 | |
8af0a70d |
171 | =head1 LIBRARY USAGE |
172 | |
173 | You can import the L<"type helpers"|/"TYPE HANDLER FUNCTIONS"> of a |
174 | library by C<use>ing it with a list of types to import as arguments. If |
175 | you want all of them, use the C<:all> tag. For example: |
176 | |
177 | use MyLibrary ':all'; |
178 | use MyOtherLibrary qw( TypeA TypeB ); |
179 | |
52d358e2 |
180 | MooseX::Types comes with a library of Moose' built-in types called |
181 | L<MooseX::Types::Moose>. |
8af0a70d |
182 | |
16ddefbf |
183 | The exporting mechanism is, since version 0.5, implemented via a wrapper |
184 | around 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 | |
191 | You can define your own wrapper subclasses to manipulate the behaviour |
192 | of 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 | |
212 | This class wraps the coercion generator (e.g., C<to_Int()>) and warns |
213 | if a coercion returned an undefined value. You can wrap any library |
214 | with 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 | |
224 | The C<Moose> library name is a special shortcut for |
52d358e2 |
225 | L<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 | |
233 | Creates a closure returning the type's L<Moose::Meta::TypeConstraint> |
234 | object. |
235 | |
236 | =item check_export_generator( $short, $full, $undef_message ) |
237 | |
238 | This 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 | |
242 | This is the closure that's doing coercions. |
243 | |
244 | =back |
245 | |
246 | =head2 Provided Parameters |
247 | |
248 | =over 4 |
249 | |
250 | =item $short |
251 | |
252 | The short, exported name of the type. |
253 | |
254 | =item $full |
255 | |
256 | The fully qualified name of this type as L<Moose> knows it. |
257 | |
258 | =item $undef_message |
259 | |
260 | A message that will be thrown when type functionality is used but the |
261 | type does not yet exist. |
262 | |
077ac262 |
263 | =head1 RECURSIVE SUBTYPES |
264 | |
265 | As of version 0.08, L<Moose::Types> has experimental support for Recursive |
266 | subtypes. This will allow: |
267 | |
268 | subtype Tree() => as HashRef[Str|Tree]; |
269 | |
270 | Which validates things like: |
271 | |
272 | {key=>'value'}; |
273 | {key=>{subkey1=>'value', subkey2=>'value'}} |
274 | |
275 | And so on. This feature is new and there may be lurking bugs so don't be afraid |
276 | to hunt me down with patches and test cases if you have trouble. |
277 | |
475bbd1d |
278 | =head1 NOTES REGARDING TYPE UNIONS |
279 | |
280 | L<MooseX::Types> uses L<MooseX::Types::TypeDecorator> to do some overloading |
281 | which generally allows you to easily create union types: |
282 | |
283 | subtype StrOrArrayRef, |
284 | as Str|ArrayRef; |
285 | |
286 | As with parameterized constrains, this overloading extends to modules using the |
287 | types 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 | |
294 | And everything should just work as you'd think. |
77134b88 |
295 | |
8af0a70d |
296 | =head1 METHODS |
297 | |
298 | =head2 import |
299 | |
52d358e2 |
300 | Installs the L<MooseX::Types::Base> class into the caller and |
e211870f |
301 | exports types according to the specification described in |
302 | L</"LIBRARY DEFINITION">. This will continue to |
303 | L<Moose::Util::TypeConstraints>' C<import> method to export helper |
304 | functions you will need to declare your types. |
305 | |
8af0a70d |
306 | =cut |
307 | |
308 | sub 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 |
345 | Generate a type export, e.g. C<Int()>. This will return either a |
346 | L<Moose::Meta::TypeConstraint> object, or alternatively a |
52d358e2 |
347 | L<MooseX::Types::UndefinedType> object if the type was not |
e211870f |
348 | yet defined. |
349 | |
8af0a70d |
350 | =cut |
351 | |
352 | sub 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 |
392 | Given a String $name with @args find the matching typeconstraint and parameterize |
393 | it with @args. |
a706b0f2 |
394 | |
395 | =cut |
396 | |
397 | sub 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 | |
405 | Given a String $name, find the matching typeconstraint. |
406 | |
407 | =cut |
408 | |
409 | sub create_base_type_constraint { |
410 | my ($class, $name) = @_; |
411 | return find_type_constraint($name); |
412 | } |
413 | |
414 | =head2 create_type_decorator ($type_constraint) |
415 | |
416 | Given a $type_constraint, return a lightweight L<MooseX::Types::TypeDecorator> |
417 | instance. |
418 | |
419 | =cut |
420 | |
421 | sub 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 |
428 | This generates a coercion handler function, e.g. C<to_Int($value)>. |
429 | |
8af0a70d |
430 | =cut |
431 | |
432 | sub 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 |
450 | Generates a constraint check closure, e.g. C<is_Int($value)>. |
451 | |
8af0a70d |
452 | =cut |
453 | |
454 | sub 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 |
468 | The following are lists of gotcha's and their workarounds for developers coming |
469 | from the standard string based type constraint names |
470 | |
471 | =head2 Uniqueness |
472 | |
e211870f |
473 | A library makes the types quasi-unique by prefixing their names with (by |
474 | default) the library package name. If you're only using the type handler |
52d358e2 |
475 | functions provided by MooseX::Types, you shouldn't ever have to use |
e211870f |
476 | a type's actual full name. |
477 | |
686e5888 |
478 | =head2 Argument separation ('=>' versus ',') |
479 | |
480 | The Perlop manpage has this to say about the '=>' operator: "The => operator is |
481 | a synonym for the comma, but forces any word (consisting entirely of word |
482 | characters) to its left to be interpreted as a string (as of 5.001). This |
483 | includes words that might otherwise be considered a constant or function call." |
484 | |
485 | Due to this stringification, the following will NOT work as you might think: |
486 | |
487 | subtype StrOrArrayRef => as Str|ArrayRef; |
488 | |
489 | The 'StrOrArrayRef' will have it's stringification activated this causes the |
490 | subtype to not be created. Since the bareword type constraints are not strings |
491 | you really should not try to treat them that way. You will have to use the ',' |
492 | operator instead. The author's of this package realize that all the L<Moose> |
493 | documention and examples nearly uniformly use the '=>' version of the comma |
494 | operator and this could be an issue if you are converting code. |
495 | |
496 | Patches welcome for discussion. |
077ac262 |
497 | |
498 | =head2 Compatibility with Sub::Exporter |
499 | |
500 | If you want to use L<Sub::Exporter> with a Type Library, you need to make sure |
501 | you export all the type constraints declared AS WELL AS any additional export |
502 | targets. 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 | |
523 | You'll get a '"MyStr" is not exported by the TypeAndSubExporter module' error. |
524 | Upi can workaround by: |
525 | |
526 | - use Sub::Exporter -setup => { exports => [ qw(something) ] }; |
527 | + use Sub::Exporter -setup => { exports => [ qw(something MyStr) ] }; |
528 | |
529 | This is a workaround and I am exploring how to make these modules work better |
530 | together. I realize this workaround will lead a lot of duplication in your |
531 | export declarations and will be onerous for large type libraries. Patches and |
532 | detailed test cases welcome. See the tests directory for a start on this. |
686e5888 |
533 | |
8af0a70d |
534 | =head1 SEE ALSO |
535 | |
16ddefbf |
536 | L<Moose>, |
537 | L<Moose::Util::TypeConstraints>, |
538 | L<MooseX::Types::Moose>, |
539 | L<Sub::Exporter> |
8af0a70d |
540 | |
541 | =head1 AUTHOR AND COPYRIGHT |
542 | |
543 | Robert 'phaylon' Sedlacek C<E<lt>rs@474.atE<gt>>, with many thanks to |
544 | the C<#moose> cabal on C<irc.perl.org>. |
545 | |
475bbd1d |
546 | Additional features by John Napiorkowski (jnapiorkowski) <jjnapiork@cpan.org>. |
547 | |
8af0a70d |
548 | =head1 LICENSE |
549 | |
550 | This program is free software; you can redistribute it and/or modify |
551 | it under the same terms as perl itself. |
552 | |
553 | =cut |
554 | |
555 | 1; |