1Specio(3)             User Contributed Perl Documentation            Specio(3)
2
3
4

NAME

6       Specio - Type constraints and coercions for Perl
7

VERSION

9       version 0.48
10

SYNOPSIS

12           package MyApp::Type::Library;
13
14           use Specio::Declare;
15           use Specio::Library::Builtins;
16
17           declare(
18               'PositiveInt',
19               parent => t('Int'),
20               inline => sub {
21                   $_[0]->parent->inline_check( $_[1] )
22                       . ' && ( '
23                       . $_[1]
24                       . ' > 0 )';
25               },
26           );
27
28           # or ...
29
30           declare(
31               'PositiveInt',
32               parent => t('Int'),
33               where  => sub { $_[0] > 0 },
34           );
35
36           declare(
37               'ArrayRefOfPositiveInt',
38               parent => t(
39                   'ArrayRef',
40                   of => t('PositiveInt'),
41               ),
42           );
43
44           coerce(
45               'ArrayRefOfPositiveInt',
46               from  => t('PositiveInt'),
47               using => sub { [ $_[0] ] },
48           );
49
50           any_can_type(
51               'Duck',
52               methods => [ 'duck_walk', 'quack' ],
53           );
54
55           object_isa_type('MyApp::Person');
56

DESCRIPTION

58       The "Specio" distribution provides classes for representing type
59       constraints and coercion, along with syntax sugar for declaring them.
60
61       Note that this is not a proper type system for Perl. Nothing in this
62       distribution will magically make the Perl interpreter start checking a
63       value's type on assignment to a variable. In fact, there's no built-in
64       way to apply a type to a variable at all.
65
66       Instead, you can explicitly check a value against a type, and
67       optionally coerce values to that type.
68
69       My long-term goal is to replace Moose's built-in types and
70       MooseX::Types with this module.
71

WHAT IS A TYPE?

73       At it's core, a type is simply a constraint. A constraint is code that
74       checks a value and returns true or false. Most constraints are
75       represented by Specio::Constraint::Simple objects. However, there are
76       other type constraint classes for specialized kinds of constraints.
77
78       Types can be named or anonymous, and each type can have a parent type.
79       A type's constraint is optional because sometimes you may want to
80       create a named subtype of some existing type without adding additional
81       constraints.
82
83       Constraints can be expressed either in terms of a simple subroutine
84       reference or in terms of an inline generator subroutine reference. The
85       former is easier to write but the latter is preferred because it allow
86       for better optimization.
87
88       A type can also have an optional message generator subroutine
89       reference. You can use this to provide a more intelligent error message
90       when a value does not pass the constraint, though the default message
91       should suffice for most cases.
92
93       Finally, you can associate a set of coercions with a type. A coercion
94       is a subroutine reference (or inline generator, like constraints), that
95       takes a value of one type and turns it into a value that matches the
96       type the coercion belongs to.
97

BUILTIN TYPES

99       This distribution ships with a set of builtin types representing the
100       types provided by the Perl interpreter itself. They are arranged in a
101       hierarchy as follows:
102
103         Item
104             Bool
105             Maybe (of `a)
106             Undef
107             Defined
108                 Value
109                     Str
110                         Num
111                             Int
112                         ClassName
113                 Ref
114                     ScalarRef (of `a)
115                     ArrayRef (of `a)
116                     HashRef (of `a)
117                     CodeRef
118                     RegexpRef
119                     GlobRef
120                     FileHandle
121                     Object
122
123       The "Item" type accepts anything and everything.
124
125       The "Bool" type only accepts "undef", 0, or 1.
126
127       The "Undef" type only accepts "undef".
128
129       The "Defined" type accepts anything except "undef".
130
131       The "Num" and "Int" types are stricter about numbers than Perl is.
132       Specifically, they do not allow any sort of space in the number, nor do
133       they accept "Nan", "Inf", or "Infinity".
134
135       The "ClassName" type constraint checks that the name is valid and that
136       the class is loaded.
137
138       The "FileHandle" type accepts either a glob, a scalar filehandle, or
139       anything that isa IO::Handle.
140
141       All types accept overloaded objects that support the required
142       operation. See below for details.
143
144   Overloading
145       Perl's overloading is horribly broken and doesn't make much sense at
146       all.
147
148       However, unlike Moose, all type constraints allow overloaded objects
149       where they make sense.
150
151       For types where overloading makes sense, we explicitly check that the
152       object provides the type overloading we expect. We do not simply try to
153       use the object as the type in question and hope it works. This means
154       that these checks effectively ignore the "fallback" setting for the
155       overloaded object. In other words, an object that overloads
156       stringification will not pass the "Bool" type check unless it also
157       overloads boolification.
158
159       Most types do not check that the overloaded method actually returns
160       something that matches the constraint. This may change in the future.
161
162       The "Bool" type accepts an object that implements "bool" overloading.
163
164       The "Str" type accepts an object that implements string ("q{""}")
165       overloading.
166
167       The "Num" type accepts an object that implements numeric ("'0+'}")
168       overloading. The "Int" type does as well, but it will check that the
169       overloading returns an actual integer.
170
171       The "ClassName" type will accept an object with string overloading that
172       returns a class name.
173
174       To make this all more confusing, the "Value" type will never accept an
175       object, even though some of its subtypes will.
176
177       The various reference types all accept objects which provide the
178       appropriate overloading. The "FileHandle" type accepts an object which
179       overloads globification as long as the returned glob is an open
180       filehandle.
181

PARAMETERIZABLE TYPES

183       Any type followed by a type parameter "of `a" in the hierarchy above
184       can be parameterized. The parameter is itself a type, so you can say
185       you want an "ArrayRef of Int", or even an "ArrayRef of HashRef of
186       ScalarRef of ClassName".
187
188       When they are parameterized, the "ScalarRef" and "ArrayRef" types check
189       that the value(s) they refer to match the type parameter. For the
190       "HashRef" type, the parameter applies to the values (keys are never
191       checked).
192
193   Maybe
194       The "Maybe" type is a special parameterized type. It allows for either
195       "undef" or a value. All by itself, it is meaningless, since it is
196       equivalent to "Maybe of Item", which is equivalent to Item. When
197       parameterized, it accepts either an "undef" or the type of its
198       parameter.
199
200       This is useful for optional attributes or parameters. However, you're
201       probably better off making your code simply not pass the parameter at
202       all This usually makes for a simpler API.
203

REGISTRIES AND IMPORTING

205       Types are local to each package where they are used. When you "import"
206       types from some other library, you are actually making a copy of that
207       type.
208
209       This means that a type named "Foo" in one package may not be the same
210       as "Foo" in another package. This has potential for confusion, but it
211       also avoids the magic action at a distance pollution that comes with a
212       global type naming system.
213
214       The registry is managed internally by the Specio distribution's
215       modules, and is not exposed to your code. To access a type, you always
216       call t('TypeName').
217
218       This returns the named type or dies if no such type exists.
219
220       Because types are always copied on import, it's safe to create
221       coercions on any type. Your coercion from "Str" to "Int" will not be
222       seen by any other package, unless that package explicitly imports your
223       "Int" type.
224
225       When you import types, you import every type defined in the package you
226       import from. However, you can overwrite an imported type with your own
227       type definition. You cannot define the same type twice internally.
228

CREATING A TYPE LIBRARY

230       By default, all types created inside a package are invisible to other
231       packages.  If you want to create a type library, you need to inherit
232       from Specio::Exporter package:
233
234         package MyApp::Type::Library;
235
236         use parent 'Specio::Exporter';
237
238         use Specio::Declare;
239         use Specio::Library::Builtins;
240
241         declare(
242             'Foo',
243             parent => t('Str'),
244             where  => sub { $_[0] =~ /foo/i },
245         );
246
247       Now the MyApp::Type::Library package will export a single type named
248       "Foo". It does not re-export the types provided by
249       Specio::Library::Builtins.
250
251       If you want to make your library re-export some other libraries types,
252       you can ask for this explicitly:
253
254         package MyApp::Type::Library;
255
256         use parent 'Specio::Exporter';
257
258         use Specio::Declare;
259         use Specio::Library::Builtins -reexport;
260
261         declare( 'Foo, ... );
262
263       Now MyApp::Types::Library exports any types it defines, as well as all
264       the types defined in Specio::Library::Builtins.
265

DECLARING TYPES

267       Use the Specio::Declare module to declare types. It exports a set of
268       helpers for declaring types. See that module's documentation for more
269       details on these helpers.
270

USING SPECIO WITH Moose

272       This should just work. Use a Specio type anywhere you'd specify a type.
273

USING SPECIO WITH Moo

275       Using Specio with Moo is easy. You can pass Specio constraint objects
276       as "isa" parameters for attributes. For coercions, simply call
277       "$type->coercion_sub".
278
279           package Foo;
280
281           use Specio::Declare;
282           use Specio::Library::Builtins;
283           use Moo;
284
285           my $str_type = t('Str');
286           has string => (
287              is  => 'ro',
288              isa => $str_type,
289           );
290
291           my $ucstr = declare(
292               'UCStr',
293               parent => t('Str'),
294               where  => sub { $_[0] =~ /^[A-Z]+$/ },
295           );
296
297           coerce(
298               $ucstr,
299               from  => t('Str'),
300               using => sub { return uc $_[0] },
301           );
302
303           has ucstr => (
304               is     => 'ro',
305               isa    => $ucstr,
306               coerce => $ucstr->coercion_sub,
307           );
308
309       The subs returned by Specio use Sub::Quote internally and are suitable
310       for inlining.
311

USING SPECIO WITH OTHER THINGS

313       See Specio::Constraint::Simple for the API that all constraint objects
314       share.
315

Moose, MooseX::Types, and Specio

317       This module aims to supplant both Moose's built-in type system (see
318       Moose::Util::TypeConstraints aka MUTC) and MooseX::Types, which
319       attempts to patch some of the holes in the Moose built-in type design.
320
321       Here are some of the salient differences:
322
323       •   Types names are strings, but they're not global
324
325           Unlike Moose and MooseX::Types, type names are always local to the
326           current package. There is no possibility of name collision between
327           different modules, so you can safely use short type names.
328
329           Unlike MooseX::Types, types are strings, so there is no possibility
330           of colliding with existing class or subroutine names.
331
332       •   No type auto-creation
333
334           Types are always retrieved using the t() subroutine. If you pass an
335           unknown name to this subroutine it dies. This is different from
336           Moose and MooseX::Types, which assume that unknown names are class
337           names.
338
339       •   Anon types are explicit
340
341           With Moose and MooseX::Types, you use the same subroutine,
342           subtype(), to declare both named and anonymous types. With Specio,
343           you use declare() for named types and anon() for anonymous types.
344
345       •   Class and object types are separate
346
347           Moose and MooseX::Types have "class_type" and "duck_type". The
348           former type requires an object, while the latter accepts a class
349           name or object.
350
351           With Specio, the distinction between accepting an object versus
352           object or class is explicit. There are six declaration helpers,
353           "object_can_type", "object_does_type", "object_isa_type",
354           "any_can_type", "any_does_type", and "any_isa_type".
355
356       •   Overloading support is baked in
357
358           Perl's overloading is quite broken but ignoring it makes Moose's
359           type system frustrating to use in many cases.
360
361       •   Types can either have a constraint or inline generator, not both
362
363           Moose and MooseX::Types types can be defined with a subroutine
364           reference as the constraint, an inline generator subroutine, or
365           both. This is purely for backwards compatibility, and it makes the
366           internals more complicated than they need to be.
367
368           With Specio, a constraint can have either a subroutine reference or
369           an inline generator, not both.
370
371       •   Coercions can be inlined
372
373           I simply never got around to implementing this in Moose.
374
375       •   No crazy coercion features
376
377           Moose has some bizarre (and mostly) undocumented features relating
378           to coercions and parameterizable types. This is a misfeature.
379

OPTIONAL PREREQS

381       There are several optional prereqs that if installed will make this
382       distribution better in some way.
383
384       •   Ref::Util
385
386           Installing this will speed up a number of type checks for built-in
387           types.
388
389       •   XString
390
391           If this is installed it will be loaded instead of the B module if
392           you have Perl 5.10 or greater. This module is much more memory
393           efficient than loading all of B.
394
395       •   Sub::Util or Sub::Name
396
397           If one of these is installed then stack traces that end up in
398           Specio code will have much better subroutine names for any frames.
399

WHY THE NAME?

401       This distro was originally called "Type", but that's an awfully generic
402       top level namespace. Specio is Latin for for "look at" and "spec" is
403       the root for the word "species". It's short, relatively easy to type,
404       and not used by any other distro.
405

LONG-TERM PLANS

407       Eventually I'd like to see this distro replace Moose's internal type
408       system, which would also make MooseX::Types obsolete.
409

SUPPORT

411       Bugs may be submitted at
412       <https://github.com/houseabsolute/Specio/issues>.
413

SOURCE

415       The source code repository for Specio can be found at
416       <https://github.com/houseabsolute/Specio>.
417

DONATIONS

419       If you'd like to thank me for the work I've done on this module, please
420       consider making a "donation" to me via PayPal. I spend a lot of free
421       time creating free software, and would appreciate any support you'd
422       care to offer.
423
424       Please note that I am not suggesting that you must do this in order for
425       me to continue working on this particular software. I will continue to
426       do so, inasmuch as I have in the past, for as long as it interests me.
427
428       Similarly, a donation made in this way will probably not make me work
429       on this software much more, unless I get so many donations that I can
430       consider working on free software full time (let's all have a chuckle
431       at that together).
432
433       To donate, log into PayPal and send money to autarch@urth.org, or use
434       the button at <https://www.urth.org/fs-donation.html>.
435

AUTHOR

437       Dave Rolsky <autarch@urth.org>
438

CONTRIBUTORS

440       •   Chris White <chrisw@leehayes.com>
441
442       •   cpansprout <cpansprout@gmail.com>
443
444       •   Graham Knop <haarg@haarg.org>
445
446       •   Karen Etheridge <ether@cpan.org>
447
448       •   Vitaly Lipatov <lav@altlinux.ru>
449
451       This software is Copyright (c) 2012 - 2022 by Dave Rolsky.
452
453       This is free software, licensed under:
454
455         The Artistic License 2.0 (GPL Compatible)
456
457       The full text of the license can be found in the LICENSE file included
458       with this distribution.
459
460
461
462perl v5.38.0                      2023-07-21                         Specio(3)
Impressum