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 Your "inline_as" block can return a list, in which case these will
121 be smushed together with "&&". The first item on the list may be
122 undef, in which case the undef will be replaced by the inlined
123 parent type constraint. (And will throw an exception if there is no
124 parent.)
125
126 declare EvenInt,
127 as Int,
128 where { $_ % 2 == 0 },
129 inline_as {
130 return (undef, "($_ % 2 == 0)");
131 };
132
133 "class_type $name, { class => $package, %options }"
134 "class_type { class => $package, %options }"
135 "class_type $name"
136 Shortcut for declaring a Type::Tiny::Class type constraint.
137
138 If $package is omitted, is assumed to be the same as $name. If
139 $name contains "::" (which would be an invalid name as far as
140 Type::Tiny is concerned), this will be removed.
141
142 So for example, "class_type("Foo::Bar")" declares a
143 Type::Tiny::Class type constraint named "FooBar" which constrains
144 values to objects blessed into the "Foo::Bar" package.
145
146 "role_type $name, { role => $package, %options }"
147 "role_type { role => $package, %options }"
148 "role_type $name"
149 Shortcut for declaring a Type::Tiny::Role type constraint.
150
151 If $package is omitted, is assumed to be the same as $name. If
152 $name contains "::" (which would be an invalid name as far as
153 Type::Tiny is concerned), this will be removed.
154
155 "duck_type $name, \@methods"
156 "duck_type \@methods"
157 Shortcut for declaring a Type::Tiny::Duck type constraint.
158
159 "union $name, \@constraints"
160 "union \@constraints"
161 Shortcut for declaring a Type::Tiny::Union type constraint.
162
163 "enum $name, \@values"
164 "enum \@values"
165 Shortcut for declaring a Type::Tiny::Enum type constraint.
166
167 "intersection $name, \@constraints"
168 "intersection \@constraints"
169 Shortcut for declaring a Type::Tiny::Intersection type constraint.
170
171 Coercion declaration functions
172 Many of the following are similar to the similarly named functions
173 described in Moose::Util::TypeConstraints.
174
175 "coerce $target, @coercions"
176 Add coercions to the target type constraint. The list of coercions
177 is a list of type constraint, conversion code pairs. Conversion
178 code can be either a string of Perl code or a coderef; in either
179 case the value to be converted is $_.
180
181 "from $source"
182 Sugar to specify a type constraint in a list of coercions:
183
184 coerce EvenInt, from Int, via { $_ * 2 }; # As a coderef...
185 coerce EvenInt, from Int, q { $_ * 2 }; # or as a string!
186
187 "via { BLOCK }"
188 Sugar to specify a coderef in a list of coercions.
189
190 "declare_coercion $name, \%opts, $type1, $code1, ..."
191 "declare_coercion \%opts, $type1, $code1, ..."
192 Declares a coercion that is not explicitly attached to any type in
193 the library. For example:
194
195 declare_coercion "ArrayRefFromAny", from "Any", via { [$_] };
196
197 This coercion will be exportable from the library as a
198 Type::Coercion object, but the ArrayRef type exported by the
199 library won't automatically use it.
200
201 Coercions declared this way are immutable (frozen).
202
203 "to_type $type"
204 Used with "declare_coercion" to declare the target type constraint
205 for a coercion, but still without explicitly attaching the coercion
206 to the type constraint:
207
208 declare_coercion "ArrayRefFromAny",
209 to_type "ArrayRef",
210 from "Any", via { [$_] };
211
212 You should pretty much always use this when declaring an unattached
213 coercion because it's exceedingly useful for a type coercion to
214 know what it will coerce to - this allows it to skip coercion when
215 no coercion is needed (e.g. avoiding coercing "[]" to "[ [] ]") and
216 allows "assert_coerce" to work properly.
217
218 Type library management
219 "extends @libraries"
220 Indicates that this type library extends other type libraries,
221 importing their type constraints.
222
223 Should usually be executed in a "BEGIN" block.
224
225 This is not exported by default because it's not fun to export it
226 to Moo, Moose or Mouse classes! "use Type::Utils -all" can be used
227 to import it into your type library.
228
229 Other
230 "match_on_type $value => ($type => \&action, ..., \&default?)"
231 Something like a "switch"/"case" or "given"/"when" construct.
232 Dispatches along different code paths depending on the type of the
233 incoming value. Example blatantly stolen from the Moose
234 documentation:
235
236 sub to_json
237 {
238 my $value = shift;
239
240 return match_on_type $value => (
241 HashRef() => sub {
242 my $hash = shift;
243 '{ '
244 . (
245 join ", " =>
246 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
247 sort keys %$hash
248 ) . ' }';
249 },
250 ArrayRef() => sub {
251 my $array = shift;
252 '[ '.( join ", " => map { to_json($_) } @$array ).' ]';
253 },
254 Num() => q {$_},
255 Str() => q { '"' . $_ . '"' },
256 Undef() => q {'null'},
257 => sub { die "$_ is not acceptable json type" },
258 );
259 }
260
261 Note that unlike Moose, code can be specified as a string instead
262 of a coderef. (e.g. for "Num", "Str" and "Undef" above.)
263
264 For improved performance, try "compile_match_on_type".
265
266 This function is not exported by default.
267
268 "my $coderef = compile_match_on_type($type => \&action, ...,
269 \&default?)"
270 Compile a "match_on_type" block into a coderef. The following JSON
271 converter is about two orders of magnitude faster than the previous
272 example:
273
274 sub to_json;
275 *to_json = compile_match_on_type(
276 HashRef() => sub {
277 my $hash = shift;
278 '{ '
279 . (
280 join ", " =>
281 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
282 sort keys %$hash
283 ) . ' }';
284 },
285 ArrayRef() => sub {
286 my $array = shift;
287 '[ '.( join ", " => map { to_json($_) } @$array ).' ]';
288 },
289 Num() => q {$_},
290 Str() => q { '"' . $_ . '"' },
291 Undef() => q {'null'},
292 => sub { die "$_ is not acceptable json type" },
293 );
294
295 Remember to store the coderef somewhere fairly permanent so that
296 you don't compile it over and over. "state" variables (in Perl >=
297 5.10) are good for this. (Same sort of idea as Type::Params.)
298
299 This function is not exported by default.
300
301 "my $coderef = classifier(@types)"
302 Returns a coderef that can be used to classify values according to
303 their type constraint. The coderef, when passed a value, returns a
304 type constraint which the value satisfies.
305
306 use feature qw( say );
307 use Type::Utils qw( classifier );
308 use Types::Standard qw( Int Num Str Any );
309
310 my $classifier = classifier(Str, Int, Num, Any);
311
312 say $classifier->( "42" )->name; # Int
313 say $classifier->( "4.2" )->name; # Num
314 say $classifier->( [] )->name; # Any
315
316 Note that, for example, "42" satisfies Int, but it would satisfy
317 the type constraints Num, Str, and Any as well. In this case, the
318 classifier has picked the most specific type constraint that "42"
319 satisfies.
320
321 If no type constraint is satisfied by the value, then the
322 classifier will return undef.
323
324 "dwim_type($string, %options)"
325 Given a string like "ArrayRef[Int|CodeRef]", turns it into a type
326 constraint object, hopefully doing what you mean.
327
328 It uses the syntax of Type::Parser. Firstly the Type::Registry for
329 the caller package is consulted; if that doesn't have a match,
330 Types::Standard is consulted for standard type constraint names.
331
332 If none of the above yields a type constraint, and the caller class
333 is a Moose-based class, then "dwim_type" attempts to look the type
334 constraint up in the Moose type registry. If it's a Mouse-based
335 class, then the Mouse type registry is used instead.
336
337 If no type constraint can be found via these normal methods,
338 several fallbacks are available:
339
340 "lookup_via_moose"
341 Lookup in Moose registry even if caller is non-Moose class.
342
343 "lookup_via_mouse"
344 Lookup in Mouse registry even if caller is non-Mouse class.
345
346 "make_class_type"
347 Create a new Type::Tiny::Class constraint.
348
349 "make_role_type"
350 Create a new Type::Tiny::Role constraint.
351
352 You can alter which should be attempted, and in which order, by
353 passing an option to "dwim_type":
354
355 my $type = Type::Utils::dwim_type(
356 "ArrayRef[Int]",
357 fallback => [ "lookup_via_mouse" , "make_role_type" ],
358 );
359
360 For historical reasons, by default the fallbacks attempted are:
361
362 lookup_via_moose, lookup_via_mouse, make_class_type
363
364 You may set "fallback" to an empty arrayref to avoid using any of
365 these fallbacks.
366
367 You can specify an alternative for the caller using the "for"
368 option.
369
370 my $type = dwim_type("ArrayRef", for => "Moose::Object");
371
372 While it's probably better overall to use the proper Type::Registry
373 interface for resolving type constraint strings, this function
374 often does what you want.
375
376 It should never die if it fails to find a type constraint (but may
377 die if the type constraint string is syntactically malformed),
378 preferring to return undef.
379
380 This function is not exported by default.
381
382 "english_list(\$conjunction, @items)"
383 Joins the items with commas, placing a conjunction before the final
384 item. The conjunction is optional, defaulting to "and".
385
386 english_list(qw/foo bar baz/); # "foo, bar, and baz"
387 english_list(\"or", qw/quux quuux/); # "quux or quuux"
388
389 This function is not exported by default.
390
392 By default, all of the functions documented above are exported, except
393 "subtype" and "type" (prefer "declare" instead), "extends",
394 "dwim_type", "match_on_type"/"compile_match_on_type", "classifier", and
395 "english_list".
396
397 This module uses Exporter::Tiny; see the documentation of that module
398 for tips and tricks importing from Type::Utils.
399
401 Please report any bugs to
402 <http://rt.cpan.org/Dist/Display.html?Queue=Type-Tiny>.
403
405 Type::Tiny::Manual.
406
407 Type::Tiny, Type::Library, Types::Standard, Type::Coercion.
408
409 Type::Tiny::Class, Type::Tiny::Role, Type::Tiny::Duck,
410 Type::Tiny::Enum, Type::Tiny::Union.
411
412 Moose::Util::TypeConstraints, Mouse::Util::TypeConstraints.
413
415 Toby Inkster <tobyink@cpan.org>.
416
418 This software is copyright (c) 2013-2014, 2017-2020 by Toby Inkster.
419
420 This is free software; you can redistribute it and/or modify it under
421 the same terms as the Perl 5 programming language system itself.
422
424 THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
425 WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
426 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
427
428
429
430perl v5.32.0 2020-09-17 Type::Utils(3)