1Specio::Declare(3) User Contributed Perl Documentation Specio::Declare(3)
2
3
4
6 Specio::Declare - Specio declaration subroutines
7
9 version 0.42
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 $_[0]->parent->inline_check( $_[1] )
144 . ' and more checking code goes here';
145 }
146
147 This parameter is mutually exclusive with the "where" parameter.
148
149 · message_generator => sub { ... }
150
151 A subroutine to generate an error message when the type check
152 fails. The default message says something like "Validation failed
153 for type named Int declared in package Specio::Library::Builtins
154 (.../Specio/blib/lib/Specio/Library/Builtins.pm) at line 147 in sub
155 named (eval) with value 1.1".
156
157 You can override this to provide something more specific about the
158 way the type failed.
159
160 The subroutine you provide will be called as a method on the type
161 with two arguments. The first is the description of the type (the
162 bit in the message above that starts with "type named Int ..." and
163 ends with "... in sub named (eval)". This description says what the
164 thing is and where it was defined.
165
166 The second argument is the value that failed the type check, after
167 any coercions that might have been applied.
168
169 anon(...)
170 This subroutine declares an anonymous type. It is identical to
171 "declare" except that it expects a list of key/value parameters without
172 a type name as the first parameter.
173
174 coerce(...)
175 This declares a coercion from one type to another. The first argument
176 should be an object which does the Specio::Constraint::Role::Interface
177 role. This can be either a named or anonymous type. This type is the
178 type that the coercion is to.
179
180 The remaining arguments are key/value parameters:
181
182 · from => $type
183
184 This must be an object which does the
185 Specio::Constraint::Role::Interface role. This is type that we are
186 coercing from. Again, this can be either a named or anonymous type.
187
188 · using => sub { ... }
189
190 This is a subroutine which defines the type coercion. It will be
191 passed a single argument, the value to coerce. It should return a
192 new value of the type this coercion is to.
193
194 This parameter is mutually exclusive with the "inline" parameter.
195
196 · inline => sub { ... }
197
198 This is a subroutine that is called to generate inline code to
199 perform the coercion.
200
201 The inline generator is called as a method on the type with one
202 argument. This argument is a string containing the variable name to
203 use in the generated code. Typically this is something like '$_[0]'
204 or '$value'.
205
206 The inline generator subroutine should return a string of code
207 representing a single term, and it should not be terminated with a
208 semicolon. This allows the inlined code to be safely included in an
209 "if" statement, for example. You can use "do { }" blocks and
210 ternaries to get everything into one term. This single term should
211 evaluate to the new value.
212
214 This module also exports some helper subs for declaring certain kinds
215 of types:
216
217 any_isa_type, object_isa_type
218 The "any_isa_type" helper creates a type which accepts a class name or
219 object of the given class. The "object_isa_type" helper creates a type
220 which only accepts an object of the given class.
221
222 These subroutines take a type name as the first argument. The remaining
223 arguments are key/value pairs. Currently this is just the "class" key,
224 which should be a class name. This is the class that the type requires.
225
226 The type name argument can be omitted to create an anonymous type.
227
228 You can also pass just a single argument, in which case that will be
229 used as both the type's name and the class for the constraint to check.
230
231 any_does_type, object_does_type
232 The "any_does_type" helper creates a type which accepts a class name or
233 object which does the given role. The "object_does_type" helper creates
234 a type which only accepts an object which does the given role.
235
236 These subroutines take a type name as the first argument. The remaining
237 arguments are key/value pairs. Currently this is just the "role" key,
238 which should be a role name. This is the class that the type requires.
239
240 This should just work (I hope) with roles created by Moose, Mouse, and
241 Moo (using Role::Tiny).
242
243 The type name argument can be omitted to create an anonymous type.
244
245 You can also pass just a single argument, in which case that will be
246 used as both the type's name and the role for the constraint to check.
247
248 any_can_type, object_can_type
249 The "any_can_type" helper creates a type which accepts a class name or
250 object with the given methods. The "object_can_type" helper creates a
251 type which only accepts an object with the given methods.
252
253 These subroutines take a type name as the first argument. The remaining
254 arguments are key/value pairs. Currently this is just the "methods"
255 key, which can be either a string or array reference of strings. These
256 strings are the required methods for the type.
257
258 The type name argument can be omitted to create an anonymous type.
259
260 enum
261 This creates a type which accepts a string matching a given list of
262 acceptable values.
263
264 The first argument is the type name. The remaining arguments are
265 key/value pairs. Currently this is just the "values" key. This should
266 an array reference of acceptable string values.
267
268 The type name argument can be omitted to create an anonymous type.
269
270 intersection
271 This creates a type which is the intersection of two or more other
272 types. A union only accepts values which match all of its underlying
273 types.
274
275 The first argument is the type name. The remaining arguments are
276 key/value pairs. Currently this is just the "of" key. This should an
277 array reference of types.
278
279 The type name argument can be omitted to create an anonymous type.
280
281 union
282 This creates a type which is the union of two or more other types. A
283 union accepts any of its underlying types.
284
285 The first argument is the type name. The remaining arguments are
286 key/value pairs. Currently this is just the "of" key. This should an
287 array reference of types.
288
289 The type name argument can be omitted to create an anonymous type.
290
292 You can create a parameterized type by calling "t" with additional
293 parameters, like this:
294
295 my $arrayref_of_int = t( 'ArrayRef', of => t('Int') );
296
297 my $arrayref_of_hashref_of_int = t(
298 'ArrayRef',
299 of => t(
300 'HashRef',
301 of => t('Int'),
302 ),
303 );
304
305 The "t" subroutine assumes that if it receives more than one argument,
306 it should look up the named type and call "$type->parameterize(...)"
307 with the additional arguments.
308
309 If the named type cannot be parameterized, it throws an error.
310
311 You can also call "$type->parameterize" directly if needed. See
312 Specio::Constraint::Parameterizable for details.
313
315 Bugs may be submitted at
316 <https://github.com/houseabsolute/Specio/issues>.
317
318 I am also usually active on IRC as 'autarch' on "irc://irc.perl.org".
319
321 The source code repository for Specio can be found at
322 <https://github.com/houseabsolute/Specio>.
323
325 Dave Rolsky <autarch@urth.org>
326
328 This software is Copyright (c) 2012 - 2017 by Dave Rolsky.
329
330 This is free software, licensed under:
331
332 The Artistic License 2.0 (GPL Compatible)
333
334 The full text of the license can be found in the LICENSE file included
335 with this distribution.
336
337
338
339perl v5.28.0 2017-11-04 Specio::Declare(3)