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