Commit | Line | Data |
ecd7cc3e |
1 | =pod |
2 | |
3 | =head1 NAME |
4 | |
d67ce58f |
5 | Moose::Manual::Types - Moose's type system |
ecd7cc3e |
6 | |
7 | =head1 TYPES IN PERL? |
8 | |
0c551c67 |
9 | Moose provides its own type system for attributes. You can also use |
10 | these types to validate method parameters with the help of a MooseX |
11 | module. |
ecd7cc3e |
12 | |
13 | Moose's type system is based on a combination of Perl 5's own |
0c551c67 |
14 | I<implicit> types and some Perl 6 concepts. You can easily create your |
15 | own subtypes with custom constraints, making it easy to express any |
16 | sort of validation. |
ecd7cc3e |
17 | |
0c551c67 |
18 | Types have names, and you can re-use them by name, making it easy to |
ecd7cc3e |
19 | share types throughout a large application. |
20 | |
21 | Let us be clear that is not a "real" type system. Moose does not |
0c551c67 |
22 | magically make Perl start associating types with variables. This is |
23 | just an advanced parameter checking system which allows you to |
24 | associate a name with a constraint. |
ecd7cc3e |
25 | |
26 | That said, it's still pretty damn useful, and we think it's one of the |
27 | things that makes Moose both fun and powerful. Taking advantage of the |
28 | type system makes it much easier to ensure that you are getting valid |
29 | data, and it also contributes greatly to code maintainability. |
30 | |
31 | =head1 THE TYPES |
32 | |
33 | The basic Moose type hierarchy looks like this |
34 | |
35 | Any |
36 | Item |
37 | Bool |
38 | Maybe[`a] |
39 | Undef |
40 | Defined |
41 | Value |
42 | Num |
43 | Int |
44 | Str |
45 | ClassName |
7612cc01 |
46 | RoleName |
ecd7cc3e |
47 | Ref |
48 | ScalarRef |
49 | ArrayRef[`a] |
50 | HashRef[`a] |
51 | CodeRef |
52 | RegexpRef |
53 | GlobRef |
54 | FileHandle |
55 | Object |
56 | Role |
57 | |
58 | In practice, the only difference between C<Any> and C<Item> is |
59 | conceptual. C<Item> is used as the top-level type in the hierarchy. |
60 | |
61 | The rest of these types correspond to existing Perl concepts. For |
dab94063 |
62 | example, a C<Num> is anything that Perl thinks looks like a number, an |
ecd7cc3e |
63 | C<Object> is a blessed reference, etc. |
64 | |
65 | The types followed by "[`a]" can be parameterized. So instead of just |
66 | plain C<ArrayRef> we can say that we want C<ArrayRef[Int]> instead. We |
67 | can even do something like C<HashRef[ArrayRef[Str]]>. |
68 | |
69 | The C<Maybe[`a]> type deserves a special mention. Used by itself, it |
70 | doesn't really mean anything (and is equivalent to C<Item>). When it |
71 | is parameterized, it means that the value is either C<undef> or the |
5a3fb5fc |
72 | parameterized type. So C<Maybe[Int]> means an integer or C<undef>. |
ecd7cc3e |
73 | |
74 | For more details on the type hierarchy, see |
75 | L<Moose::Util::TypeConstraints>. |
76 | |
77 | =head1 WHAT IS A TYPE? |
78 | |
79 | It's important to realize that types are not classes (or |
80 | packages). Types are just objects (L<Moose::Meta::TypeConstraint> |
0c551c67 |
81 | objects, to be exact) with a name and a constraint. Moose maintains a |
6549b0d1 |
82 | global type registry that lets it convert names like C<Num> into the |
0c551c67 |
83 | appropriate object. |
ecd7cc3e |
84 | |
85 | However, class names I<can be> type names. When you define a new class |
86 | using Moose, it defines an associated type name behind the scenes: |
87 | |
88 | package MyApp::User; |
89 | |
90 | use Moose; |
91 | |
92 | Now you can use C<'MyApp::User'> as a type name: |
93 | |
94 | has creator => ( |
6c5b976f |
95 | is => 'ro', |
ecd7cc3e |
96 | isa => 'MyApp::User', |
97 | ); |
98 | |
99 | However, for non-Moose classes there's no magic. You may have to |
100 | explicitly declare the class type. This is a bit muddled because Moose |
101 | assumes that any unknown type name passed as the C<isa> value for an |
102 | attribute is a class. So this works: |
103 | |
104 | has 'birth_date' => ( |
6c5b976f |
105 | is => 'ro', |
ecd7cc3e |
106 | isa => 'DateTime', |
107 | ); |
108 | |
109 | In general, when Moose is presented with an unknown name, it assumes |
110 | that the name is a class: |
111 | |
112 | subtype 'ModernDateTime' |
113 | => as 'DateTime' |
114 | => where { $_->year() >= 1980 } |
115 | => message { 'The date you provided is not modern enough' }; |
116 | |
117 | has 'valid_dates' => ( |
118 | is => 'ro', |
119 | isa => 'ArrayRef[DateTime]', |
120 | ); |
121 | |
0c39debe |
122 | Moose will assume that C<DateTime> is a class name in both of these |
0c551c67 |
123 | instances. |
ecd7cc3e |
124 | |
125 | =head1 SUBTYPES |
126 | |
dab94063 |
127 | Moose uses subtypes in its built-in hierarchy. For example, C<Int> is |
128 | a child of C<Num>. |
ecd7cc3e |
129 | |
130 | A subtype is defined in terms of a parent type and a constraint. Any |
dab94063 |
131 | constraints defined by the parent(s) will be checked first, followed by |
132 | constraints defined by the subtype. A value must pass I<all> of these |
133 | checks to be valid for the subtype. |
ecd7cc3e |
134 | |
0c551c67 |
135 | Typically, a subtype takes the parent's constraint and makes it more |
ecd7cc3e |
136 | specific. |
137 | |
138 | A subtype can also define its own constraint failure message. This |
139 | lets you do things like have an error "The value you provided (20), |
140 | was not a valid rating, which must be a number from 1-10." This is |
141 | much friendlier than the default error, which just says that the value |
142 | failed a validation check for the type. |
143 | |
144 | Here's a simple (and useful) subtype example: |
145 | |
146 | subtype 'PositiveInt' |
147 | => as 'Int' |
148 | => where { $_ > 0 } |
149 | => message { "The number you provided, $_, was not a positive number" } |
150 | |
151 | Note that the sugar functions for working with types are all exported |
152 | by L<Moose::Util::TypeConstraints>. |
153 | |
d67ce58f |
154 | =head2 Creating a new type (that isn't a subtype) |
ecd7cc3e |
155 | |
156 | You can also create new top-level types: |
157 | |
158 | type 'FourCharacters' => where { defined $_ && length $_ == 4 }; |
159 | |
0c551c67 |
160 | In practice, this example is more or less the same as subtyping |
636f25f3 |
161 | C<Str>, except you have to check definedness yourself. |
ecd7cc3e |
162 | |
163 | It's hard to find a case where you wouldn't want to subtype a very |
164 | broad type like C<Defined>, C<Ref> or C<Object>. |
165 | |
0c551c67 |
166 | Defining a new top-level type is conceptually the same as subtyping |
167 | C<Item>. |
ecd7cc3e |
168 | |
169 | =head1 TYPE NAMES |
170 | |
171 | Type names are global throughout the current Perl |
0c551c67 |
172 | interpreter. Internally, Moose maps names to type objects via a |
173 | L<registry|Moose::Meta::TypeConstraint::Registry>. |
ecd7cc3e |
174 | |
175 | If you have multiple apps or libraries all using Moose in the same |
176 | process, you could have problems with collisions. We recommend that |
177 | you prefix names with some sort of namespace indicator to prevent |
178 | these sorts of collisions. |
179 | |
180 | For example, instead of calling a type "PositiveInt", call it |
bcc22289 |
181 | "MyApp::Type::PositiveInt" or "MyApp::Types::PositiveInt". We |
182 | recommend that you centralize all of these definitions in a single |
183 | package, C<MyApp::Types>, which can be loaded by other classes in your |
184 | application. |
ecd7cc3e |
185 | |
06712014 |
186 | Once you're doing this, you should almost certainly look at the |
187 | L<MooseX::Types> extension which allows easy declaration of type libraries |
188 | and can export your types as perl constants so that you can refer to them |
189 | as just |
190 | |
191 | has 'counter' => (is => 'rw', isa => PositiveInt); |
192 | |
193 | rather than needing to fully qualify them everywhere. It also allows |
194 | |
195 | has 'counts' => (is => 'ro', isa => HashRef[PositiveInt]); |
196 | |
aacca3ab |
197 | and similarly for the union and other syntax discussed below, which |
06712014 |
198 | will compile time check your use of names and is generally more robust |
199 | than the string type parsing for complex cases. |
200 | |
ecd7cc3e |
201 | =head1 COERCION |
202 | |
203 | One of the most powerful features of Moose's type system is its |
0c551c67 |
204 | coercions. A coercion is a way to convert from one type to another. |
ecd7cc3e |
205 | |
206 | subtype 'ArrayRefOfInts' |
207 | => as 'ArrayRef[Int]'; |
208 | |
209 | coerce 'ArrayRefOfInts' |
210 | => from 'Int' |
211 | => via { [ $_ ] }; |
212 | |
213 | You'll note that we had to create a subtype rather than coercing |
214 | C<ArrayRef[Int]> directly. This is just a quirk of how Moose |
215 | works. |
216 | |
217 | Coercions, like type names, are global. This is I<another> reason why |
218 | it is good to namespace your types. Moose will I<never> try to coerce |
219 | a value unless you explicitly ask for it. This is done by setting the |
16fb3624 |
220 | C<coerce> attribute option to a true value: |
ecd7cc3e |
221 | |
222 | package Foo; |
223 | |
224 | has 'sizes' => ( |
6c5b976f |
225 | is => 'ro', |
ecd7cc3e |
226 | isa => 'ArrayRefOfInts', |
227 | coerce => 1, |
228 | ); |
229 | |
230 | Foo->new( sizes => 42 ); |
231 | |
232 | This code example will do the right thing, and the newly created |
233 | object will have C<[ 42 ]> as its C<sizes> attribute. |
234 | |
d67ce58f |
235 | =head2 Deep coercion |
ecd7cc3e |
236 | |
237 | Deep coercion is the coercion of type parameters for parameterized |
238 | types. Let's take these types as an example: |
239 | |
240 | subtype 'HexNum' |
241 | => as 'Str' |
242 | => where { /[a-f0-9]/i }; |
243 | |
244 | coerce 'Int' |
245 | => from 'HexNum' |
246 | => via { hex $_ }; |
247 | |
248 | has 'sizes' => ( |
6c5b976f |
249 | is => 'ro', |
ecd7cc3e |
250 | isa => 'ArrayRef[Int]', |
251 | coerce => 1, |
252 | ); |
253 | |
254 | If we try passing an array reference of hex numbers for the C<sizes> |
0c551c67 |
255 | attribute, Moose will not do any coercion. |
ecd7cc3e |
256 | |
0c551c67 |
257 | However, you can define a set of subtypes to enable coercion between |
258 | two parameterized types. |
ecd7cc3e |
259 | |
260 | subtype 'ArrayRefOfHexNums' |
261 | => as 'ArrayRef[HexNum]'; |
262 | |
263 | subtype 'ArrayRefOfInts' |
264 | => as 'ArrayRef[Int]'; |
265 | |
266 | coerce 'ArrayRefOfInts' |
267 | => from 'ArrayRefOfHexNums' |
268 | => via { [ map { hex } @{$_} ] }; |
269 | |
270 | Foo->new( sizes => [ 'a1', 'ff', '22' ] ); |
271 | |
272 | Now Moose will coerce the hex numbers to integers. |
273 | |
0c551c67 |
274 | However, Moose does not attempt to chain coercions, so it will not |
275 | coerce a single hex number. To do that, we need to define a separate |
276 | coercion: |
ecd7cc3e |
277 | |
278 | coerce 'ArrayRefOfInts' |
279 | => from 'HexNum' |
280 | => via { [ hex $_ ] }; |
281 | |
282 | Yes, this can all get verbose, but coercion is tricky magic, and we |
0c551c67 |
283 | think it's best to make it explicit. |
ecd7cc3e |
284 | |
285 | =head1 TYPE UNIONS |
286 | |
287 | Moose allows you to say that an attribute can be of two or more |
288 | disparate types. For example, we might allow an C<Object> or |
289 | C<FileHandle>: |
290 | |
291 | has 'output' => ( |
292 | is => 'rw', |
293 | isa => 'Object | FileHandle', |
294 | ); |
295 | |
296 | Moose actually parses that string and recognizes that you are creating |
297 | a type union. The C<output> attribute will accept any sort of object, |
298 | as well as an unblessed file handle. It is up to you to do the right |
299 | thing for each of them in your code. |
300 | |
0c551c67 |
301 | Whenever you use a type union, you should consider whether or not |
302 | coercion might be a better answer. |
ecd7cc3e |
303 | |
304 | For our example above, we might want to be more specific, and insist |
305 | that output be an object with a C<print> method: |
306 | |
307 | subtype 'CanPrint' |
308 | => as 'Object' |
309 | => where { $_->can('print') }; |
310 | |
311 | We can coerce file handles to an object that satisfies this condition |
312 | with a simple wrapper class: |
313 | |
314 | package FHWrapper; |
315 | |
316 | use Moose; |
317 | |
318 | has 'handle' => ( |
6c5b976f |
319 | is => 'rw', |
ecd7cc3e |
320 | isa => 'FileHandle', |
321 | ); |
322 | |
323 | sub print { |
324 | my $self = shift; |
325 | my $fh = $self->handle(); |
326 | |
327 | print $fh @_; |
328 | } |
329 | |
330 | Now we can define a coercion from C<FileHandle> to our wrapper class: |
331 | |
0c551c67 |
332 | coerce 'CanPrint' |
ecd7cc3e |
333 | => from 'FileHandle' |
334 | => via { FHWrapper->new( handle => $_ ) }; |
335 | |
336 | has 'output' => ( |
337 | is => 'rw', |
338 | isa => 'CanPrint', |
339 | coerce => 1, |
340 | ); |
341 | |
0c551c67 |
342 | This pattern of using a coercion instead of a type union will help |
343 | make your class internals simpler. |
ecd7cc3e |
344 | |
345 | =head1 TYPE CREATION HELPERS |
346 | |
347 | The L<Moose::Util::TypeConstraints> module exports a number of helper |
348 | functions for creating specific kinds of types. These include |
349 | C<class_type>, C<role_type>, and C<maybe_type>. See the docs for |
350 | details. |
351 | |
352 | One helper worth noting is C<enum>, which allows you to create a |
353 | subtype of C<Str> that only allows the specified values: |
354 | |
355 | enum 'RGB' => qw( red green blue ); |
356 | |
dab94063 |
357 | This creates a type named C<RGB>. |
ecd7cc3e |
358 | |
359 | =head1 ANONYMOUS TYPES |
360 | |
361 | All of the type creation functions return a type object. This type |
362 | object can be used wherever you would use a type name, as a parent |
16fb3624 |
363 | type, or as the value for an attribute's C<isa> option: |
ecd7cc3e |
364 | |
365 | has 'size' => ( |
6c5b976f |
366 | is => 'ro', |
ecd7cc3e |
367 | isa => subtype 'Int' => where { $_ > 0 }, |
368 | ); |
369 | |
370 | This is handy when you want to create a one-off type and don't want to |
371 | "pollute" the global namespace registry. |
372 | |
373 | =head1 VALIDATING METHOD PARAMETERS |
374 | |
375 | Moose does not provide any means of validating method |
376 | parameters. However, there are several MooseX extensions on CPAN which |
377 | let you do this. |
378 | |
0c39debe |
379 | The simplest and least sugary is L<MooseX::Params::Validate>. This |
ecd7cc3e |
380 | lets you validate a set of named parameters using Moose types: |
381 | |
382 | use Moose; |
383 | use MooseX::Params::Validate; |
384 | |
385 | sub foo { |
386 | my $self = shift; |
0c551c67 |
387 | my %params = validated_hash( |
ecd7cc3e |
388 | \@_, |
389 | bar => { isa => 'Str', default => 'Moose' }, |
390 | ); |
391 | ... |
392 | } |
393 | |
0c39debe |
394 | L<MooseX::Params::Validate> also supports coercions. |
ecd7cc3e |
395 | |
396 | There are several more powerful extensions that support method |
397 | parameter validation using Moose types, including |
0c39debe |
398 | L<MooseX::Method::Signatures>, which gives you a full-blown C<method> |
ecd7cc3e |
399 | keyword. |
400 | |
401 | method morning (Str $name) { |
402 | $self->say("Good morning ${name}!"); |
403 | } |
404 | |
ca680d1f |
405 | =head1 LOAD ORDER ISSUES |
406 | |
0c551c67 |
407 | Because Moose types are defined at runtime, you may run into load |
408 | order problems. In particular, you may want to use a class's type |
409 | constraint before that type has been defined. |
ca680d1f |
410 | |
0c551c67 |
411 | We have several recommendations for ameliorating this problem. First, |
412 | define I<all> of your custom types in one module, |
413 | C<MyApp::Types>. Second, load this module in all of your other |
414 | modules. |
ca680d1f |
415 | |
416 | If you are still having load order problems, you can make use of the |
417 | C<find_type_constraint> function exported by |
418 | L<Moose::Util::TypeConstraints>: |
419 | |
0c551c67 |
420 | class_type('MyApp::User') |
5a3fb5fc |
421 | unless find_type_constraint('MyApp::User'); |
ca680d1f |
422 | |
423 | This sort of "find or create" logic is simple to write, and will let |
424 | you work around load order issues. |
425 | |
ecd7cc3e |
426 | =head1 AUTHOR |
427 | |
428 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
429 | |
430 | =head1 COPYRIGHT AND LICENSE |
431 | |
2840a3b2 |
432 | Copyright 2009 by Infinity Interactive, Inc. |
ecd7cc3e |
433 | |
434 | L<http://www.iinteractive.com> |
435 | |
436 | This library is free software; you can redistribute it and/or modify |
437 | it under the same terms as Perl itself. |
438 | |
439 | =cut |