{"id":7422,"date":"2022-12-20T19:38:02","date_gmt":"2022-12-20T22:38:02","guid":{"rendered":"http:\/\/lode.uno\/linux-man\/index.php\/2022\/12\/20\/specio-man3\/"},"modified":"2022-12-20T19:38:02","modified_gmt":"2022-12-20T22:38:02","slug":"specio-man3","status":"publish","type":"post","link":"https:\/\/lode.uno\/linux-man\/2022\/12\/20\/specio-man3\/","title":{"rendered":"Specio (man3)"},"content":{"rendered":"<h1 align=\"center\">Specio<\/h1>\n<p> <a href=\"#NAME\">NAME<\/a><br \/> <a href=\"#VERSION\">VERSION<\/a><br \/> <a href=\"#SYNOPSIS\">SYNOPSIS<\/a><br \/> <a href=\"#DESCRIPTION\">DESCRIPTION<\/a><br \/> <a href=\"#WHAT IS A TYPE?\">WHAT IS A TYPE?<\/a><br \/> <a href=\"#BUILTIN TYPES\">BUILTIN TYPES<\/a><br \/> <a href=\"#PARAMETERIZABLE TYPES\">PARAMETERIZABLE TYPES<\/a><br \/> <a href=\"#REGISTRIES AND IMPORTING\">REGISTRIES AND IMPORTING<\/a><br \/> <a href=\"#CREATING A TYPE LIBRARY\">CREATING A TYPE LIBRARY<\/a><br \/> <a href=\"#DECLARING TYPES\">DECLARING TYPES<\/a><br \/> <a href=\"#USING SPECIO WITH Moose\">USING SPECIO WITH Moose<\/a><br \/> <a href=\"#USING SPECIO WITH Moo\">USING SPECIO WITH Moo<\/a><br \/> <a href=\"#USING SPECIO WITH OTHER THINGS\">USING SPECIO WITH OTHER THINGS<\/a><br \/> <a href=\"#Moose, MooseX::Types, and Specio\">Moose, MooseX::Types, and Specio<\/a><br \/> <a href=\"#OPTIONAL PREREQS\">OPTIONAL PREREQS<\/a><br \/> <a href=\"#WHY THE NAME?\">WHY THE NAME?<\/a><br \/> <a href=\"#LONG-TERM PLANS\">LONG-TERM PLANS<\/a><br \/> <a href=\"#SUPPORT\">SUPPORT<\/a><br \/> <a href=\"#SOURCE\">SOURCE<\/a><br \/> <a href=\"#DONATIONS\">DONATIONS<\/a><br \/> <a href=\"#AUTHOR\">AUTHOR<\/a><br \/> <a href=\"#CONTRIBUTORS\">CONTRIBUTORS<\/a><br \/> <a href=\"#COPYRIGHT AND LICENSE\">COPYRIGHT AND LICENSE<\/a> <\/p>\n<hr>\n<h2>NAME <a name=\"NAME\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Specio \u2212 Type constraints and coercions for Perl<\/p>\n<h2>VERSION <a name=\"VERSION\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">version 0.46<\/p>\n<h2>SYNOPSIS <a name=\"SYNOPSIS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">package MyApp::Type::Library; <br \/> use Specio::Declare; <br \/> use Specio::Library::Builtins; <br \/> declare( <br \/> &#8216;PositiveInt&#8217;, <br \/> parent => t(&#8216;Int&#8217;), <br \/> inline => sub { <br \/> $_[0]\u2212>parent\u2212>inline_check( $_[1] ) <br \/> . &#8216; &#038;&#038; ( &#8216; <br \/> . $_[1] <br \/> . &#8216; > 0 )&#8217;; <br \/> }, <br \/> ); <br \/> # or &#8230; <br \/> declare( <br \/> &#8216;PositiveInt&#8217;, <br \/> parent => t(&#8216;Int&#8217;), <br \/> where => sub { $_[0] > 0 }, <br \/> ); <br \/> declare( <br \/> &#8216;ArrayRefOfPositiveInt&#8217;, <br \/> parent => t( <br \/> &#8216;ArrayRef&#8217;, <br \/> of => t(&#8216;PositiveInt&#8217;), <br \/> ), <br \/> ); <br \/> coerce( <br \/> &#8216;ArrayRefOfPositiveInt&#8217;, <br \/> from => t(&#8216;PositiveInt&#8217;), <br \/> using => sub { [ $_[0] ] }, <br \/> ); <br \/> any_can_type( <br \/> &#8216;Duck&#8217;, <br \/> methods => [ &#8216;duck_walk&#8217;, &#8216;quack&#8217; ], <br \/> ); <br \/> object_isa_type(&#8216;MyApp::Person&#8217;);<\/p>\n<h2>DESCRIPTION <a name=\"DESCRIPTION\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Specio&#8221; distribution provides classes for representing type constraints and coercion, along with syntax sugar for declaring them.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Note that this is not a proper type system for Perl. Nothing in this distribution will magically make the Perl interpreter start checking a value\u2019s type on assignment to a variable. In fact, there\u2019s no built-in way to apply a type to a variable at all.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Instead, you can explicitly check a value against a type, and optionally coerce values to that type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">My long-term goal is to replace Moose\u2019s built-in types and MooseX::Types with this module.<\/p>\n<h2>WHAT IS A TYPE? <a name=\"WHAT IS A TYPE?\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">At it\u2019s core, a type is simply a constraint. A constraint is code that checks a value and returns true or false. Most constraints are represented by Specio::Constraint::Simple objects. However, there are other type constraint classes for specialized kinds of constraints.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Types can be named or anonymous, and each type can have a parent type. A type\u2019s constraint is optional because sometimes you may want to create a named subtype of some existing type without adding additional constraints.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Constraints can be expressed either in terms of a simple subroutine reference or in terms of an inline generator subroutine reference. The former is easier to write but the latter is preferred because it allow for better optimization.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">A type can also have an optional message generator subroutine reference. You can use this to provide a more intelligent error message when a value does not pass the constraint, though the default message should suffice for most cases.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Finally, you can associate a set of coercions with a type. A coercion is a subroutine reference (or inline generator, like constraints), that takes a value of one type and turns it into a value that matches the type the coercion belongs to.<\/p>\n<h2>BUILTIN TYPES <a name=\"BUILTIN TYPES\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This distribution ships with a set of builtin types representing the types provided by the Perl interpreter itself. They are arranged in a hierarchy as follows:<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Item <br \/> Bool <br \/> Maybe (of `a) <br \/> Undef <br \/> Defined <br \/> Value <br \/> Str <br \/> Num <br \/> Int <br \/> ClassName <br \/> Ref <br \/> ScalarRef (of `a) <br \/> ArrayRef (of `a) <br \/> HashRef (of `a) <br \/> CodeRef <br \/> RegexpRef <br \/> GlobRef <br \/> FileHandle <br \/> Object<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Item&#8221; type accepts anything and everything.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Bool&#8221; type only accepts &#8220;undef&#8221;, 0, or 1.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Undef&#8221; type only accepts &#8220;undef&#8221;.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Defined&#8221; type accepts anything <i>except<\/i> &#8220;undef&#8221;.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Num&#8221; and &#8220;Int&#8221; types are stricter about numbers than Perl is. Specifically, they do not allow any sort of space in the number, nor do they accept &#8220;Nan&#8221;, &#8220;Inf&#8221;, or &#8220;Infinity&#8221;.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;ClassName&#8221; type constraint checks that the name is valid <i>and<\/i> that the class is loaded.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;FileHandle&#8221; type accepts either a glob, a scalar filehandle, or anything that isa IO::Handle.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">All types accept overloaded objects that support the required operation. See below for details.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Overloading<\/b> <br \/> Perl\u2019s overloading is horribly broken and doesn\u2019t make much sense at all.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">However, unlike Moose, all type constraints allow overloaded objects where they make sense.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">For types where overloading makes sense, we explicitly check that the object provides the type overloading we expect. We <i>do not<\/i> simply try to use the object as the type in question and hope it works. This means that these checks effectively ignore the &#8220;fallback&#8221; setting for the overloaded object. In other words, an object that overloads stringification will not pass the &#8220;Bool&#8221; type check unless it <i>also<\/i> overloads boolification.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Most types do not check that the overloaded method actually returns something that matches the constraint. This may change in the future.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Bool&#8221; type accepts an object that implements &#8220;bool&#8221; overloading.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Str&#8221; type accepts an object that implements string (&#8220;q{&#8220;&#8221;}&#8221;) overloading.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;Num&#8221; type accepts an object that implements numeric (&#8220;&#8216;0+&#8217;}&#8221;) overloading. The &#8220;Int&#8221; type does as well, but it will check that the overloading returns an actual integer.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;ClassName&#8221; type will accept an object with string overloading that returns a class name.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">To make this all more confusing, the &#8220;Value&#8221; type will <i>never<\/i> accept an object, even though some of its subtypes will.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The various reference types all accept objects which provide the appropriate overloading. The &#8220;FileHandle&#8221; type accepts an object which overloads globification as long as the returned glob is an open filehandle.<\/p>\n<h2>PARAMETERIZABLE TYPES <a name=\"PARAMETERIZABLE TYPES\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Any type followed by a type parameter &#8220;of `a&#8221; in the hierarchy above can be parameterized. The parameter is itself a type, so you can say you want an &#8220;ArrayRef of Int&#8221;, or even an &#8220;ArrayRef of HashRef of ScalarRef of ClassName&#8221;.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">When they are parameterized, the &#8220;ScalarRef&#8221; and &#8220;ArrayRef&#8221; types check that the value(s) they refer to match the type parameter. For the &#8220;HashRef&#8221; type, the parameter applies to the values (keys are never checked).<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>Maybe<\/b> <br \/> The &#8220;Maybe&#8221; type is a special parameterized type. It allows for either &#8220;undef&#8221; or a value. All by itself, it is meaningless, since it is equivalent to &#8220;Maybe of Item&#8221;, which is equivalent to Item. When parameterized, it accepts either an &#8220;undef&#8221; or the type of its parameter.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">This is useful for optional attributes or parameters. However, you\u2019re probably better off making your code simply not pass the parameter at all This usually makes for a simpler <small>API.<\/small><\/p>\n<h2>REGISTRIES AND IMPORTING <a name=\"REGISTRIES AND IMPORTING\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Types are local to each package where they are used. When you &#8220;import&#8221; types from some other library, you are actually making a copy of that type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">This means that a type named &#8220;Foo&#8221; in one package may not be the same as &#8220;Foo&#8221; in another package. This has potential for confusion, but it also avoids the magic action at a distance pollution that comes with a global type naming system.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The registry is managed internally by the Specio distribution\u2019s modules, and is not exposed to your code. To access a type, you always call &#8220;t(&#8216;TypeName&#8217;)&#8221;.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">This returns the named type or dies if no such type exists.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Because types are always copied on import, it\u2019s safe to create coercions on any type. Your coercion from &#8220;Str&#8221; to &#8220;Int&#8221; will not be seen by any other package, unless that package explicitly imports your &#8220;Int&#8221; type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">When you import types, you import every type defined in the package you import from. However, you <i>can<\/i> overwrite an imported type with your own type definition. You <i>cannot<\/i> define the same type twice internally.<\/p>\n<h2>CREATING A TYPE LIBRARY <a name=\"CREATING A TYPE LIBRARY\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">By default, all types created inside a package are invisible to other packages. If you want to create a type library, you need to inherit from Specio::Exporter package:<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">package MyApp::Type::Library; <br \/> use parent &#8216;Specio::Exporter&#8217;; <br \/> use Specio::Declare; <br \/> use Specio::Library::Builtins; <br \/> declare( <br \/> &#8216;Foo&#8217;, <br \/> parent => t(&#8216;Str&#8217;), <br \/> where => sub { $_[0] =~ \/foo\/i }, <br \/> );<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Now the MyApp::Type::Library package will export a single type named &#8220;Foo&#8221;. It <i>does not<\/i> re-export the types provided by Specio::Library::Builtins.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">If you want to make your library re-export some other libraries types, you can ask for this explicitly:<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">package MyApp::Type::Library; <br \/> use parent &#8216;Specio::Exporter&#8217;; <br \/> use Specio::Declare; <br \/> use Specio::Library::Builtins \u2212reexport; <br \/> declare( &#8216;Foo, &#8230; );<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Now MyApp::Types::Library exports any types it defines, as well as all the types defined in Specio::Library::Builtins.<\/p>\n<h2>DECLARING TYPES <a name=\"DECLARING TYPES\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Use the Specio::Declare module to declare types. It exports a set of helpers for declaring types. See that module\u2019s documentation for more details on these helpers.<\/p>\n<h2>USING SPECIO WITH Moose <a name=\"USING SPECIO WITH Moose\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This should just work. Use a Specio type anywhere you\u2019d specify a type.<\/p>\n<h2>USING SPECIO WITH Moo <a name=\"USING SPECIO WITH Moo\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Using Specio with Moo is easy. You can pass Specio constraint objects as &#8220;isa&#8221; parameters for attributes. For coercions, simply call &#8220;$type\u2212>coercion_sub&#8221;.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">package Foo; <br \/> use Specio::Declare; <br \/> use Specio::Library::Builtins; <br \/> use Moo; <br \/> my $str_type = t(&#8216;Str&#8217;); <br \/> has string => ( <br \/> is => &#8216;ro&#8217;, <br \/> isa => $str_type, <br \/> ); <br \/> my $ucstr = declare( <br \/> &#8216;UCStr&#8217;, <br \/> parent => t(&#8216;Str&#8217;), <br \/> where => sub { $_[0] =~ \/^[A\u2212Z]+$\/ }, <br \/> ); <br \/> coerce( <br \/> $ucstr, <br \/> from => t(&#8216;Str&#8217;), <br \/> using => sub { return uc $_[0] }, <br \/> ); <br \/> has ucstr => ( <br \/> is => &#8216;ro&#8217;, <br \/> isa => $ucstr, <br \/> coerce => $ucstr\u2212>coercion_sub, <br \/> );<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The subs returned by Specio use Sub::Quote internally and are suitable for inlining.<\/p>\n<h2>USING SPECIO WITH OTHER THINGS <a name=\"USING SPECIO WITH OTHER THINGS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">See Specio::Constraint::Simple for the <small>API<\/small> that all constraint objects share.<\/p>\n<h2>Moose, MooseX::Types, and Specio <a name=\"Moose, MooseX::Types, and Specio\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This module aims to supplant both Moose\u2019s built-in type system (see Moose::Util::TypeConstraints aka <small>MUTC<\/small> ) and MooseX::Types, which attempts to patch some of the holes in the Moose built-in type design.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Here are some of the salient differences:<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"72%\">\n<p>Types names are strings, but they\u2019re not global<\/p>\n<\/td>\n<td width=\"11%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Unlike Moose and MooseX::Types, type names are always local to the current package. There is no possibility of name collision between different modules, so you can safely use short type names.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">Unlike MooseX::Types, types are strings, so there is no possibility of colliding with existing class or subroutine names.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"32%\">\n<p style=\"margin-top: 1em\">No type auto-creation<\/p>\n<\/td>\n<td width=\"51%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Types are always retrieved using the &#8220;t()&#8221; subroutine. If you pass an unknown name to this subroutine it dies. This is different from Moose and MooseX::Types, which assume that unknown names are class names.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"35%\">\n<p style=\"margin-top: 1em\">Anon types are explicit<\/p>\n<\/td>\n<td width=\"48%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">With Moose and MooseX::Types, you use the same subroutine, &#8220;subtype()&#8221;, to declare both named and anonymous types. With Specio, you use &#8220;declare()&#8221; for named types and &#8220;anon()&#8221; for anonymous types.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"54%\">\n<p style=\"margin-top: 1em\">Class and object types are separate<\/p>\n<\/td>\n<td width=\"29%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Moose and MooseX::Types have &#8220;class_type&#8221; and &#8220;duck_type&#8221;. The former type requires an object, while the latter accepts a class name or object.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">With Specio, the distinction between accepting an object versus object or class is explicit. There are six declaration helpers, &#8220;object_can_type&#8221;, &#8220;object_does_type&#8221;, &#8220;object_isa_type&#8221;, &#8220;any_can_type&#8221;, &#8220;any_does_type&#8221;, and &#8220;any_isa_type&#8221;.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"48%\">\n<p style=\"margin-top: 1em\">Overloading support is baked in<\/p>\n<\/td>\n<td width=\"35%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Perl\u2019s overloading is quite broken but ignoring it makes Moose\u2019s type system frustrating to use in many cases.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"83%\">\n<p style=\"margin-top: 1em\">Types can either have a constraint or inline generator, not both<\/p>\n<\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Moose and MooseX::Types types can be defined with a subroutine reference as the constraint, an inline generator subroutine, or both. This is purely for backwards compatibility, and it makes the internals more complicated than they need to be.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">With Specio, a constraint can have <i>either<\/i> a subroutine reference or an inline generator, not both.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"37%\">\n<p style=\"margin-top: 1em\">Coercions can be inlined<\/p>\n<\/td>\n<td width=\"46%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">I simply never got around to implementing this in Moose.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"40%\">\n<p style=\"margin-top: 1em\">No crazy coercion features<\/p>\n<\/td>\n<td width=\"43%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Moose has some bizarre (and mostly) undocumented features relating to coercions and parameterizable types. This is a misfeature.<\/p>\n<h2>OPTIONAL PREREQS <a name=\"OPTIONAL PREREQS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">There are several optional prereqs that if installed will make this distribution better in some way.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"14%\">\n<p style=\"margin-top: 1em\">Ref::Util<\/p>\n<\/td>\n<td width=\"69%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">Installing this will speed up a number of type checks for built-in types.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"11%\">\n<p style=\"margin-top: 1em\">XString<\/p>\n<\/td>\n<td width=\"72%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">If this is installed it will be loaded instead of the B module if you have Perl 5.10 or greater. This module is much more memory efficient than loading all of B.<\/p>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"34%\">\n<p style=\"margin-top: 1em\">Sub::Util or Sub::Name<\/p>\n<\/td>\n<td width=\"49%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">If one of these is installed then stack traces that end up in Specio code will have much better subroutine names for any frames.<\/p>\n<h2>WHY THE NAME? <a name=\"WHY THE NAME?\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This distro was originally called &#8220;Type&#8221;, but that\u2019s an awfully generic top level namespace. Specio is Latin for for &#8220;look at&#8221; and &#8220;spec&#8221; is the root for the word &#8220;species&#8221;. It\u2019s short, relatively easy to type, and not used by any other distro.<\/p>\n<h2>LONG-TERM PLANS <a name=\"LONG-TERM PLANS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Eventually I\u2019d like to see this distro replace Moose\u2019s internal type system, which would also make MooseX::Types obsolete.<\/p>\n<h2>SUPPORT <a name=\"SUPPORT\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Bugs may be submitted at <https:\/\/github.com\/houseabsolute\/Specio\/issues>.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">I am also usually active on <small>IRC<\/small> as \u2019autarch\u2019 on &#8220;irc:\/\/irc.perl.org&#8221;.<\/p>\n<h2>SOURCE <a name=\"SOURCE\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">The source code repository for Specio can be found at <https:\/\/github.com\/houseabsolute\/Specio>.<\/p>\n<h2>DONATIONS <a name=\"DONATIONS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">If you\u2019d like to thank me for the work I\u2019ve done on this module, please consider making a &#8220;donation&#8221; to me via PayPal. I spend a lot of free time creating free software, and would appreciate any support you\u2019d care to offer.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Please note that <b>I am not suggesting that you must do this<\/b> in order for me to continue working on this particular software. I will continue to do so, inasmuch as I have in the past, for as long as it interests me.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">Similarly, a donation made in this way will probably not make me work on this software much more, unless I get so many donations that I can consider working on free software full time (let\u2019s all have a chuckle at that together).<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">To donate, log into PayPal and send money to autarch@urth.org, or use the button at <https:\/\/www.urth.org\/fs\u2212donation.html>.<\/p>\n<h2>AUTHOR <a name=\"AUTHOR\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Dave Rolsky <autarch@urth.org><\/p>\n<h2>CONTRIBUTORS <a name=\"CONTRIBUTORS\"><\/a> <\/h2>\n<table width=\"100%\" border=\"0\" rules=\"none\" frame=\"void\" cellspacing=\"0\" cellpadding=\"0\">\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p style=\"margin-top: 1em\">\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"51%\">\n<p style=\"margin-top: 1em\">Chris White <chrisw@leehayes.com><\/p>\n<\/td>\n<td width=\"32%\"> <\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"51%\">\n<p>cpansprout <cpansprout@gmail.com><\/p>\n<\/td>\n<td width=\"32%\"> <\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"51%\">\n<p>Graham Knop <haarg@haarg.org><\/p>\n<\/td>\n<td width=\"32%\"> <\/td>\n<\/tr>\n<tr valign=\"top\" align=\"left\">\n<td width=\"11%\"><\/td>\n<td width=\"1%\">\n<p>\u2022<\/p>\n<\/td>\n<td width=\"5%\"><\/td>\n<td width=\"51%\">\n<p>Karen Etheridge <ether@cpan.org><\/p>\n<\/td>\n<td width=\"32%\"> <\/td>\n<\/tr>\n<\/table>\n<h2>COPYRIGHT AND LICENSE <a name=\"COPYRIGHT AND LICENSE\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This software is Copyright (c) 2012 \u2212 2020 by Dave Rolsky.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">This is free software, licensed under:<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The Artistic License 2.0 (GPL Compatible)<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The full text of the license can be found in the <i><small>LICENSE<\/small><\/i> file included with this distribution.<\/p>\n<hr>\n","protected":false},"excerpt":{"rendered":"<p>  Specio \u2212 Type constraints and coercions for Perl <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[3007,3734],"class_list":["post-7422","post","type-post","status-publish","format-standard","hentry","category-sin-categoria","tag-man3","tag-specio"],"gutentor_comment":0,"_links":{"self":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts\/7422","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/comments?post=7422"}],"version-history":[{"count":0,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts\/7422\/revisions"}],"wp:attachment":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/media?parent=7422"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/categories?post=7422"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/tags?post=7422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}