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