1Specio::Declare(3) User Contributed Perl Documentation Specio::Declare(3)
2
3
4
6 Specio::Declare - Specio declaration subroutines
7
9 version 0.47
10
12 package MyApp::Type::Library;
13
14 use parent 'Specio::Exporter';
15
16 use Specio::Declare;
17 use Specio::Library::Builtins;
18
19 declare(
20 'Foo',
21 parent => t('Str'),
22 where => sub { $_[0] =~ /foo/i },
23 );
24
25 declare(
26 'ArrayRefOfInt',
27 parent => t( 'ArrayRef', of => t('Int') ),
28 );
29
30 my $even = anon(
31 parent => t('Int'),
32 inline => sub {
33 my $type = shift;
34 my $value_var = shift;
35
36 return $value_var . ' % 2 == 0';
37 },
38 );
39
40 coerce(
41 t('ArrayRef'),
42 from => t('Foo'),
43 using => sub { [ $_[0] ] },
44 );
45
46 coerce(
47 $even,
48 from => t('Int'),
49 using => sub { $_[0] % 2 ? $_[0] + 1 : $_[0] },
50 );
51
52 # Specio name is DateTime
53 any_isa_type('DateTime');
54
55 # Specio name is DateTimeObject
56 object_isa_type( 'DateTimeObject', class => 'DateTime' );
57
58 any_can_type(
59 'Duck',
60 methods => [ 'duck_walk', 'quack' ],
61 );
62
63 object_can_type(
64 'DuckObject',
65 methods => [ 'duck_walk', 'quack' ],
66 );
67
68 enum(
69 'Colors',
70 values => [qw( blue green red )],
71 );
72
73 intersection(
74 'HashRefAndArrayRef',
75 of => [ t('HashRef'), t('ArrayRef') ],
76 );
77
78 union(
79 'IntOrArrayRef',
80 of => [ t('Int'), t('ArrayRef') ],
81 );
82
84 This package exports a set of type declaration helpers. Importing this
85 package also causes it to create a "t" subroutine the caller.
86
88 This module exports the following subroutines.
89
90 t('name')
91 This subroutine lets you access any types you have declared so far, as
92 well as any types you imported from another type library.
93
94 If you pass an unknown name, it throws an exception.
95
96 declare(...)
97 This subroutine declares a named type. The first argument is the type
98 name, followed by a set of key/value parameters:
99
100 • parent => $type
101
102 The parent should be another type object. Specifically, it can be
103 anything which does the Specio::Constraint::Role::Interface role.
104 The parent can be a named or anonymous type.
105
106 • where => sub { ... }
107
108 This is a subroutine which defines the type constraint. It will be
109 passed a single argument, the value to check, and it should return
110 true or false to indicate whether or not the value is valid for the
111 type.
112
113 This parameter is mutually exclusive with the "inline" parameter.
114
115 • inline => sub { ... }
116
117 This is a subroutine that is called to generate inline code to
118 validate the type. Inlining can be much faster than simply
119 providing a subroutine with the "where" parameter, but is often
120 more complicated to get right.
121
122 The inline generator is called as a method on the type with one
123 argument. This argument is a string containing the variable name to
124 use in the generated code. Typically this is something like '$_[0]'
125 or '$value'.
126
127 The inline generator subroutine should return a string of code
128 representing a single term, and it should not be terminated with a
129 semicolon. This allows the inlined code to be safely included in an
130 "if" statement, for example. You can use "do { }" blocks and
131 ternaries to get everything into one term. Do not assign to the
132 variable you are testing. This single term should evaluate to true
133 or false.
134
135 The inline generator is expected to include code to implement both
136 the current type and all its parents. Typically, the easiest way to
137 do this is to write a subroutine something like this:
138
139 sub {
140 my $self = shift;
141 my $var = shift;
142
143 return $self->parent->inline_check($var)
144 . ' and more checking code goes here';
145 }
146
147 Or, more concisely:
148
149 sub { $_[0]->parent->inline_check( $_[1] ) . 'more code that checks $_[1]' }
150
151 The "inline" parameter is mutually exclusive with the "where"
152 parameter.
153
154 • message_generator => sub { ... }
155
156 A subroutine to generate an error message when the type check
157 fails. The default message says something like "Validation failed
158 for type named Int declared in package Specio::Library::Builtins
159 (.../Specio/blib/lib/Specio/Library/Builtins.pm) at line 147 in sub
160 named (eval) with value 1.1".
161
162 You can override this to provide something more specific about the
163 way the type failed.
164
165 The subroutine you provide will be called as a method on the type
166 with two arguments. The first is the description of the type (the
167 bit in the message above that starts with "type named Int ..." and
168 ends with "... in sub named (eval)". This description says what the
169 thing is and where it was defined.
170
171 The second argument is the value that failed the type check, after
172 any coercions that might have been applied.
173
174 anon(...)
175 This subroutine declares an anonymous type. It is identical to
176 "declare" except that it expects a list of key/value parameters without
177 a type name as the first parameter.
178
179 coerce(...)
180 This declares a coercion from one type to another. The first argument
181 should be an object which does the Specio::Constraint::Role::Interface
182 role. This can be either a named or anonymous type. This type is the
183 type that the coercion is to.
184
185 The remaining arguments are key/value parameters:
186
187 • from => $type
188
189 This must be an object which does the
190 Specio::Constraint::Role::Interface role. This is type that we are
191 coercing from. Again, this can be either a named or anonymous type.
192
193 • using => sub { ... }
194
195 This is a subroutine which defines the type coercion. It will be
196 passed a single argument, the value to coerce. It should return a
197 new value of the type this coercion is to.
198
199 This parameter is mutually exclusive with the "inline" parameter.
200
201 • inline => sub { ... }
202
203 This is a subroutine that is called to generate inline code to
204 perform the coercion.
205
206 The inline generator is called as a method on the type with one
207 argument. This argument is a string containing the variable name to
208 use in the generated code. Typically this is something like '$_[0]'
209 or '$value'.
210
211 The inline generator subroutine should return a string of code
212 representing a single term, and it should not be terminated with a
213 semicolon. This allows the inlined code to be safely included in an
214 "if" statement, for example. You can use "do { }" blocks and
215 ternaries to get everything into one term. This single term should
216 evaluate to the new value.
217
219 This module also exports some helper subs for declaring certain kinds
220 of types:
221
222 any_isa_type, object_isa_type
223 The "any_isa_type" helper creates a type which accepts a class name or
224 object of the given class. The "object_isa_type" helper creates a type
225 which only accepts an object of the given class.
226
227 These subroutines take a type name as the first argument. The remaining
228 arguments are key/value pairs. Currently this is just the "class" key,
229 which should be a class name. This is the class that the type requires.
230
231 The type name argument can be omitted to create an anonymous type.
232
233 You can also pass just a single argument, in which case that will be
234 used as both the type's name and the class for the constraint to check.
235
236 any_does_type, object_does_type
237 The "any_does_type" helper creates a type which accepts a class name or
238 object which does the given role. The "object_does_type" helper creates
239 a type which only accepts an object which does the given role.
240
241 These subroutines take a type name as the first argument. The remaining
242 arguments are key/value pairs. Currently this is just the "role" key,
243 which should be a role name. This is the class that the type requires.
244
245 This should just work (I hope) with roles created by Moose, Mouse, and
246 Moo (using Role::Tiny).
247
248 The type name argument can be omitted to create an anonymous type.
249
250 You can also pass just a single argument, in which case that will be
251 used as both the type's name and the role for the constraint to check.
252
253 any_can_type, object_can_type
254 The "any_can_type" helper creates a type which accepts a class name or
255 object with the given methods. The "object_can_type" helper creates a
256 type which only accepts an object with the given methods.
257
258 These subroutines take a type name as the first argument. The remaining
259 arguments are key/value pairs. Currently this is just the "methods"
260 key, which can be either a string or array reference of strings. These
261 strings are the required methods for the type.
262
263 The type name argument can be omitted to create an anonymous type.
264
265 enum
266 This creates a type which accepts a string matching a given list of
267 acceptable values.
268
269 The first argument is the type name. The remaining arguments are
270 key/value pairs. Currently this is just the "values" key. This should
271 an array reference of acceptable string values.
272
273 The type name argument can be omitted to create an anonymous type.
274
275 intersection
276 This creates a type which is the intersection of two or more other
277 types. A union only accepts values which match all of its underlying
278 types.
279
280 The first argument is the type name. The remaining arguments are
281 key/value pairs. Currently this is just the "of" key. This should an
282 array reference of types.
283
284 The type name argument can be omitted to create an anonymous type.
285
286 union
287 This creates a type which is the union of two or more other types. A
288 union accepts any of its underlying types.
289
290 The first argument is the type name. The remaining arguments are
291 key/value pairs. Currently this is just the "of" key. This should an
292 array reference of types.
293
294 The type name argument can be omitted to create an anonymous type.
295
297 You can create a parameterized type by calling "t" with additional
298 parameters, like this:
299
300 my $arrayref_of_int = t( 'ArrayRef', of => t('Int') );
301
302 my $arrayref_of_hashref_of_int = t(
303 'ArrayRef',
304 of => t(
305 'HashRef',
306 of => t('Int'),
307 ),
308 );
309
310 The "t" subroutine assumes that if it receives more than one argument,
311 it should look up the named type and call "$type->parameterize(...)"
312 with the additional arguments.
313
314 If the named type cannot be parameterized, it throws an error.
315
316 You can also call "$type->parameterize" directly if needed. See
317 Specio::Constraint::Parameterizable for details.
318
320 Bugs may be submitted at
321 <https://github.com/houseabsolute/Specio/issues>.
322
323 I am also usually active on IRC as 'autarch' on "irc://irc.perl.org".
324
326 The source code repository for Specio can be found at
327 <https://github.com/houseabsolute/Specio>.
328
330 Dave Rolsky <autarch@urth.org>
331
333 This software is Copyright (c) 2012 - 2021 by Dave Rolsky.
334
335 This is free software, licensed under:
336
337 The Artistic License 2.0 (GPL Compatible)
338
339 The full text of the license can be found in the LICENSE file included
340 with this distribution.
341
342
343
344perl v5.34.0 2022-01-21 Specio::Declare(3)