1Type::Utils(3) User Contributed Perl Documentation Type::Utils(3)
2
3
4
6 Type::Utils - utility functions to make defining and using type
7 constraints a little easier
8
10 package Types::Mine;
11
12 use Type::Library -base;
13 use Type::Utils -all;
14
15 BEGIN { extends "Types::Standard" };
16
17 declare "AllCaps",
18 as "Str",
19 where { uc($_) eq $_ },
20 inline_as { my $varname = $_[1]; "uc($varname) eq $varname" };
21
22 coerce "AllCaps",
23 from "Str", via { uc($_) };
24
26 This module is covered by the Type-Tiny stability policy.
27
29 This module provides utility functions to make defining and using type
30 constraints a little easier.
31
32 Type declaration functions
33 Many of the following are similar to the similarly named functions
34 described in Moose::Util::TypeConstraints.
35
36 "declare $name, %options"
37 "declare %options"
38 Declare a named or anonymous type constraint. Use "as" and "where"
39 to specify the parent type (if any) and (possibly) refine its
40 definition.
41
42 declare EvenInt, as Int, where { $_ % 2 == 0 };
43
44 my $EvenInt = declare as Int, where { $_ % 2 == 0 };
45
46 NOTE: If the caller package inherits from Type::Library then any
47 non-anonymous types declared in the package will be automatically
48 installed into the library.
49
50 Hidden gem: if you're inheriting from a type constraint that
51 includes some coercions, you can include "coercion => 1" in the
52 %options hash to inherit the coercions.
53
54 "subtype $name, %options"
55 "subtype %options"
56 Declare a named or anonymous type constraint which is descended
57 from an existing type constraint. Use "as" and "where" to specify
58 the parent type and refine its definition.
59
60 Actually, you should use "declare" instead; this is just an alias.
61
62 This function is not exported by default.
63
64 "type $name, %options"
65 "type %options"
66 Declare a named or anonymous type constraint which is not descended
67 from an existing type constraint. Use "where" to provide a coderef
68 that constrains values.
69
70 Actually, you should use "declare" instead; this is just an alias.
71
72 This function is not exported by default.
73
74 "as $parent"
75 Used with "declare" to specify a parent type constraint:
76
77 declare EvenInt, as Int, where { $_ % 2 == 0 };
78
79 "where { BLOCK }"
80 Used with "declare" to provide the constraint coderef:
81
82 declare EvenInt, as Int, where { $_ % 2 == 0 };
83
84 The coderef operates on $_, which is the value being tested.
85
86 "message { BLOCK }"
87 Generate a custom error message when a value fails validation.
88
89 declare EvenInt,
90 as Int,
91 where { $_ % 2 == 0 },
92 message {
93 Int->validate($_) or "$_ is not divisible by two";
94 };
95
96 Without a custom message, the messages generated by Type::Tiny are
97 along the lines of Value "33" did not pass type constraint
98 "EvenInt", which is usually reasonable.
99
100 "inline_as { BLOCK }"
101 Generate a string of Perl code that can be used to inline the type
102 check into other functions. If your type check is being used within
103 a Moose or Moo constructor or accessor methods, or used by
104 Type::Params, this can lead to significant performance
105 improvements.
106
107 declare EvenInt,
108 as Int,
109 where { $_ % 2 == 0 },
110 inline_as {
111 my ($constraint, $varname) = @_;
112 my $perlcode =
113 $constraint->parent->inline_check($varname)
114 . "&& ($varname % 2 == 0)";
115 return $perlcode;
116 };
117
118 warn EvenInt->inline_check('$xxx'); # demonstration
119
120 Experimental: your "inline_as" block can return a list, in which
121 case these will be smushed together with "&&". The first item on
122 the list may be undef, in which case the undef will be replaced by
123 the inlined parent type constraint. (And will throw an exception if
124 there is no parent.)
125
126 declare EvenInt,
127 as Int,
128 where { $_ % 2 == 0 },
129 inline_as {
130 return (undef, "($_ % 2 == 0)");
131 };
132
133 Returning a list like this is considered experimental, is not
134 tested very much, and I offer no guarantees that it will
135 necessarily work with Moose/Mouse/Moo.
136
137 "class_type $name, { class => $package, %options }"
138 "class_type { class => $package, %options }"
139 "class_type $name"
140 Shortcut for declaring a Type::Tiny::Class type constraint.
141
142 If $package is omitted, is assumed to be the same as $name. If
143 $name contains "::" (which would be an invalid name as far as
144 Type::Tiny is concerned), this will be removed.
145
146 So for example, "class_type("Foo::Bar")" declares a
147 Type::Tiny::Class type constraint named "FooBar" which constrains
148 values to objects blessed into the "Foo::Bar" package.
149
150 "role_type $name, { role => $package, %options }"
151 "role_type { role => $package, %options }"
152 "role_type $name"
153 Shortcut for declaring a Type::Tiny::Role type constraint.
154
155 If $package is omitted, is assumed to be the same as $name. If
156 $name contains "::" (which would be an invalid name as far as
157 Type::Tiny is concerned), this will be removed.
158
159 "duck_type $name, \@methods"
160 "duck_type \@methods"
161 Shortcut for declaring a Type::Tiny::Duck type constraint.
162
163 "union $name, \@constraints"
164 "union \@constraints"
165 Shortcut for declaring a Type::Tiny::Union type constraint.
166
167 "enum $name, \@values"
168 "enum \@values"
169 Shortcut for declaring a Type::Tiny::Enum type constraint.
170
171 "intersection $name, \@constraints"
172 "intersection \@constraints"
173 Shortcut for declaring a Type::Tiny::Intersection type constraint.
174
175 Coercion declaration functions
176 Many of the following are similar to the similarly named functions
177 described in Moose::Util::TypeConstraints.
178
179 "coerce $target, @coercions"
180 Add coercions to the target type constraint. The list of coercions
181 is a list of type constraint, conversion code pairs. Conversion
182 code can be either a string of Perl code or a coderef; in either
183 case the value to be converted is $_.
184
185 "from $source"
186 Sugar to specify a type constraint in a list of coercions:
187
188 coerce EvenInt, from Int, via { $_ * 2 }; # As a coderef...
189 coerce EvenInt, from Int, q { $_ * 2 }; # or as a string!
190
191 "via { BLOCK }"
192 Sugar to specify a coderef in a list of coercions.
193
194 "declare_coercion $name, \%opts, $type1, $code1, ..."
195 "declare_coercion \%opts, $type1, $code1, ..."
196 Declares a coercion that is not explicitly attached to any type in
197 the library. For example:
198
199 declare_coercion "ArrayRefFromAny", from "Any", via { [$_] };
200
201 This coercion will be exportable from the library as a
202 Type::Coercion object, but the ArrayRef type exported by the
203 library won't automatically use it.
204
205 Coercions declared this way are immutable (frozen).
206
207 "to_type $type"
208 Used with "declare_coercion" to declare the target type constraint
209 for a coercion, but still without explicitly attaching the coercion
210 to the type constraint:
211
212 declare_coercion "ArrayRefFromAny",
213 to_type "ArrayRef",
214 from "Any", via { [$_] };
215
216 You should pretty much always use this when declaring an unattached
217 coercion because it's exceedingly useful for a type coercion to
218 know what it will coerce to - this allows it to skip coercion when
219 no coercion is needed (e.g. avoiding coercing "[]" to "[ [] ]") and
220 allows "assert_coerce" to work properly.
221
222 Type library management
223 "extends @libraries"
224 Indicates that this type library extends other type libraries,
225 importing their type constraints.
226
227 Should usually be executed in a "BEGIN" block.
228
229 This is not exported by default because it's not fun to export it
230 to Moo, Moose or Mouse classes! "use Type::Utils -all" can be used
231 to import it into your type library.
232
233 Other
234 "match_on_type $value => ($type => \&action, ..., \&default?)"
235 Something like a "switch"/"case" or "given"/"when" construct.
236 Dispatches along different code paths depending on the type of the
237 incoming value. Example blatantly stolen from the Moose
238 documentation:
239
240 sub to_json
241 {
242 my $value = shift;
243
244 return match_on_type $value => (
245 HashRef() => sub {
246 my $hash = shift;
247 '{ '
248 . (
249 join ", " =>
250 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
251 sort keys %$hash
252 ) . ' }';
253 },
254 ArrayRef() => sub {
255 my $array = shift;
256 '[ '.( join ", " => map { to_json($_) } @$array ).' ]';
257 },
258 Num() => q {$_},
259 Str() => q { '"' . $_ . '"' },
260 Undef() => q {'null'},
261 => sub { die "$_ is not acceptable json type" },
262 );
263 }
264
265 Note that unlike Moose, code can be specified as a string instead
266 of a coderef. (e.g. for "Num", "Str" and "Undef" above.)
267
268 For improved performance, try "compile_match_on_type".
269
270 This function is not exported by default.
271
272 "my $coderef = compile_match_on_type($type => \&action, ...,
273 \&default?)"
274 Compile a "match_on_type" block into a coderef. The following JSON
275 converter is about two orders of magnitude faster than the previous
276 example:
277
278 sub to_json;
279 *to_json = compile_match_on_type(
280 HashRef() => sub {
281 my $hash = shift;
282 '{ '
283 . (
284 join ", " =>
285 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
286 sort keys %$hash
287 ) . ' }';
288 },
289 ArrayRef() => sub {
290 my $array = shift;
291 '[ '.( join ", " => map { to_json($_) } @$array ).' ]';
292 },
293 Num() => q {$_},
294 Str() => q { '"' . $_ . '"' },
295 Undef() => q {'null'},
296 => sub { die "$_ is not acceptable json type" },
297 );
298
299 Remember to store the coderef somewhere fairly permanent so that
300 you don't compile it over and over. "state" variables (in Perl >=
301 5.10) are good for this. (Same sort of idea as Type::Params.)
302
303 This function is not exported by default.
304
305 "my $coderef = classifier(@types)"
306 Returns a coderef that can be used to classify values according to
307 their type constraint. The coderef, when passed a value, returns a
308 type constraint which the value satisfies.
309
310 use feature qw( say );
311 use Type::Utils qw( classifier );
312 use Types::Standard qw( Int Num Str Any );
313
314 my $classifier = classifier(Str, Int, Num, Any);
315
316 say $classifier->( "42" )->name; # Int
317 say $classifier->( "4.2" )->name; # Num
318 say $classifier->( [] )->name; # Any
319
320 Note that, for example, "42" satisfies Int, but it would satisfy
321 the type constraints Num, Str, and Any as well. In this case, the
322 classifier has picked the most specific type constraint that "42"
323 satisfies.
324
325 If no type constraint is satisfied by the value, then the
326 classifier will return undef.
327
328 "dwim_type($string, %options)"
329 Given a string like "ArrayRef[Int|CodeRef]", turns it into a type
330 constraint object, hopefully doing what you mean.
331
332 It uses the syntax of Type::Parser. Firstly the Type::Registry for
333 the caller package is consulted; if that doesn't have a match,
334 Types::Standard is consulted for standard type constraint names.
335
336 If none of the above yields a type constraint, and the caller class
337 is a Moose-based class, then "dwim_type" attempts to look the type
338 constraint up in the Moose type registry. If it's a Mouse-based
339 class, then the Mouse type registry is used instead.
340
341 If no type constraint can be found via these normal methods,
342 several fallbacks are available:
343
344 "lookup_via_moose"
345 Lookup in Moose registry even if caller is non-Moose class.
346
347 "lookup_via_mouse"
348 Lookup in Mouse registry even if caller is non-Mouse class.
349
350 "make_class_type"
351 Create a new Type::Tiny::Class constraint.
352
353 "make_role_type"
354 Create a new Type::Tiny::Role constraint.
355
356 You can alter which should be attempted, and in which order, by
357 passing an option to "dwim_type":
358
359 my $type = Type::Utils::dwim_type(
360 "ArrayRef[Int]",
361 fallback => [ "lookup_via_mouse" , "make_role_type" ],
362 );
363
364 For historical reasons, by default the fallbacks attempted are:
365
366 lookup_via_moose, lookup_via_mouse, make_class_type
367
368 You may set "fallback" to an empty arrayref to avoid using any of
369 these fallbacks.
370
371 You can specify an alternative for the caller using the "for"
372 option.
373
374 my $type = dwim_type("ArrayRef", for => "Moose::Object");
375
376 While it's probably better overall to use the proper Type::Registry
377 interface for resolving type constraint strings, this function
378 often does what you want.
379
380 It should never die if it fails to find a type constraint (but may
381 die if the type constraint string is syntactically malformed),
382 preferring to return undef.
383
384 This function is not exported by default.
385
386 "english_list(\$conjunction, @items)"
387 Joins the items with commas, placing a conjunction before the final
388 item. The conjunction is optional, defaulting to "and".
389
390 english_list(qw/foo bar baz/); # "foo, bar, and baz"
391 english_list(\"or", qw/quux quuux/); # "quux or quuux"
392
393 This function is not exported by default.
394
396 By default, all of the functions documented above are exported, except
397 "subtype" and "type" (prefer "declare" instead), "extends",
398 "dwim_type", "match_on_type"/"compile_match_on_type", "classifier", and
399 "english_list".
400
401 This module uses Exporter::Tiny; see the documentation of that module
402 for tips and tricks importing from Type::Utils.
403
405 Please report any bugs to
406 <http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.
407
409 Type::Tiny::Manual.
410
411 Type::Tiny, Type::Library, Types::Standard, Type::Coercion.
412
413 Type::Tiny::Class, Type::Tiny::Role, Type::Tiny::Duck,
414 Type::Tiny::Enum, Type::Tiny::Union.
415
416 Moose::Util::TypeConstraints, Mouse::Util::TypeConstraints.
417
419 Toby Inkster <tobyink@cpan.org>.
420
422 This software is copyright (c) 2013-2014, 2017-2019 by Toby Inkster.
423
424 This is free software; you can redistribute it and/or modify it under
425 the same terms as the Perl 5 programming language system itself.
426
428 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
429 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
430 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
431
432
433
434perl v5.30.0 2019-07-26 Type::Utils(3)