{"id":6895,"date":"2022-12-20T19:34:16","date_gmt":"2022-12-20T22:34:16","guid":{"rendered":"http:\/\/lode.uno\/linux-man\/index.php\/2022\/12\/20\/speciodeclare-man3\/"},"modified":"2022-12-20T19:34:16","modified_gmt":"2022-12-20T22:34:16","slug":"speciodeclare-man3","status":"publish","type":"post","link":"https:\/\/lode.uno\/linux-man\/2022\/12\/20\/speciodeclare-man3\/","title":{"rendered":"Specio::Declare (man3)"},"content":{"rendered":"<h1 align=\"center\">Specio::Declare<\/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=\"#SUBROUTINES\">SUBROUTINES<\/a><br \/> <a href=\"#DECLARATION HELPERS\">DECLARATION HELPERS<\/a><br \/> <a href=\"#PARAMETERIZED TYPES\">PARAMETERIZED TYPES<\/a><br \/> <a href=\"#SUPPORT\">SUPPORT<\/a><br \/> <a href=\"#SOURCE\">SOURCE<\/a><br \/> <a href=\"#AUTHOR\">AUTHOR<\/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::Declare \u2212 Specio declaration subroutines<\/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 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 \/> ); <br \/> declare( <br \/> &#8216;ArrayRefOfInt&#8217;, <br \/> parent => t( &#8216;ArrayRef&#8217;, of => t(&#8216;Int&#8217;) ), <br \/> ); <br \/> my $even = anon( <br \/> parent => t(&#8216;Int&#8217;), <br \/> inline => sub { <br \/> my $type = shift; <br \/> my $value_var = shift; <br \/> return $value_var . &#8216; % 2 == 0&#8217;; <br \/> }, <br \/> ); <br \/> coerce( <br \/> t(&#8216;ArrayRef&#8217;), <br \/> from => t(&#8216;Foo&#8217;), <br \/> using => sub { [ $_[0] ] }, <br \/> ); <br \/> coerce( <br \/> $even, <br \/> from => t(&#8216;Int&#8217;), <br \/> using => sub { $_[0] % 2 ? $_[0] + 1 : $_[0] }, <br \/> ); <br \/> # Specio name is DateTime <br \/> any_isa_type(&#8216;DateTime&#8217;); <br \/> # Specio name is DateTimeObject <br \/> object_isa_type( &#8216;DateTimeObject&#8217;, class => &#8216;DateTime&#8217; ); <br \/> any_can_type( <br \/> &#8216;Duck&#8217;, <br \/> methods => [ &#8216;duck_walk&#8217;, &#8216;quack&#8217; ], <br \/> ); <br \/> object_can_type( <br \/> &#8216;DuckObject&#8217;, <br \/> methods => [ &#8216;duck_walk&#8217;, &#8216;quack&#8217; ], <br \/> ); <br \/> enum( <br \/> &#8216;Colors&#8217;, <br \/> values => [qw( blue green red )], <br \/> ); <br \/> intersection( <br \/> &#8216;HashRefAndArrayRef&#8217;, <br \/> of => [ t(&#8216;HashRef&#8217;), t(&#8216;ArrayRef&#8217;) ], <br \/> ); <br \/> union( <br \/> &#8216;IntOrArrayRef&#8217;, <br \/> of => [ t(&#8216;Int&#8217;), t(&#8216;ArrayRef&#8217;) ], <br \/> );<\/p>\n<h2>DESCRIPTION <a name=\"DESCRIPTION\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This package exports a set of type declaration helpers. Importing this package also causes it to create a &#8220;t&#8221; subroutine the caller.<\/p>\n<h2>SUBROUTINES <a name=\"SUBROUTINES\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This module exports the following subroutines.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>t(\u2019name\u2019)<\/b> <br \/> This subroutine lets you access any types you have declared so far, as well as any types you imported from another type library.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">If you pass an unknown name, it throws an exception.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>declare(&#8230;)<\/b> <br \/> This subroutine declares a named type. The first argument is the type name, followed by a set of key\/value parameters:<\/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=\"23%\">\n<p>parent => $type<\/p>\n<\/td>\n<td width=\"60%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">The parent should be another type object. Specifically, it can be anything which does the Specio::Constraint::Role::Interface role. The parent can be a named or anonymous type.<\/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=\"31%\">\n<p style=\"margin-top: 1em\">where => sub { &#8230; }<\/p>\n<\/td>\n<td width=\"52%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">This is a subroutine which defines the type constraint. It will be passed a single argument, the value to check, and it should return true or false to indicate whether or not the value is valid for the type.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">This parameter is mutually exclusive with the &#8220;inline&#8221; parameter.<\/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\">inline => sub { &#8230; }<\/p>\n<\/td>\n<td width=\"51%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">This is a subroutine that is called to generate inline code to validate the type. Inlining can be <i>much<\/i> faster than simply providing a subroutine with the &#8220;where&#8221; parameter, but is often more complicated to get right.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The inline generator is called as a method on the type with one argument. This argument is a <i>string<\/i> containing the variable name to use in the generated code. Typically this is something like &#8216;$_[0]&#8217; or &#8216;$value&#8217;.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The inline generator subroutine should return a <i>string<\/i> of code representing a single term, and it <i>should not<\/i> be terminated with a semicolon. This allows the inlined code to be safely included in an &#8220;if&#8221; statement, for example. You can use &#8220;do { }&#8221; blocks and ternaries to get everything into one term. Do not assign to the variable you are testing. This single term should evaluate to true or false.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The inline generator is expected to include code to implement both the current type and all its parents. Typically, the easiest way to do this is to write a subroutine something like this:<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">sub { <br \/> my $self = shift; <br \/> my $var = shift; <br \/> return $self\u2212>parent\u2212>inline_check($var) <br \/> . &#8216; and more checking code goes here&#8217;; <br \/> }<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">Or, more concisely:<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">sub { $_[0]\u2212>parent\u2212>inline_check( $_[1] ) . &#8216;more code that checks $_[1]&#8217; }<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The &#8220;inline&#8221; parameter is mutually exclusive with the &#8220;where&#8221; parameter.<\/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=\"49%\">\n<p style=\"margin-top: 1em\">message_generator => sub { &#8230; }<\/p>\n<\/td>\n<td width=\"34%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">A subroutine to generate an error message when the type check fails. The default message says something like &#8220;Validation failed for type named Int declared in package Specio::Library::Builtins (&#8230;\/Specio\/blib\/lib\/Specio\/Library\/Builtins.pm) at line 147 in sub named (eval) with value 1.1&#8221;.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">You can override this to provide something more specific about the way the type failed.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The subroutine you provide will be called as a method on the type with two arguments. The first is the description of the type (the bit in the message above that starts with &#8220;type named Int &#8230;&#8221; and ends with &#8220;&#8230; in sub named (eval)&#8221;. This description says what the thing is and where it was defined.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The second argument is the value that failed the type check, after any coercions that might have been applied.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>anon(&#8230;)<\/b> <br \/> This subroutine declares an anonymous type. It is identical to &#8220;declare&#8221; except that it expects a list of key\/value parameters without a type name as the first parameter.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>coerce(&#8230;)<\/b> <br \/> This declares a coercion from one type to another. The first argument should be an object which does the Specio::Constraint::Role::Interface role. This can be either a named or anonymous type. This type is the type that the coercion is <i>to<\/i>.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The remaining arguments are key\/value parameters:<\/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=\"20%\">\n<p style=\"margin-top: 1em\">from => $type<\/p>\n<\/td>\n<td width=\"63%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">This must be an object which does the Specio::Constraint::Role::Interface role. This is type that we are coercing <i>from<\/i>. Again, this can be either a named or anonymous type.<\/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=\"31%\">\n<p style=\"margin-top: 1em\">using => sub { &#8230; }<\/p>\n<\/td>\n<td width=\"52%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">This is a subroutine which defines the type coercion. It will be passed a single argument, the value to coerce. It should return a new value of the type this coercion is to.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">This parameter is mutually exclusive with the &#8220;inline&#8221; parameter.<\/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\">inline => sub { &#8230; }<\/p>\n<\/td>\n<td width=\"51%\"> <\/td>\n<\/tr>\n<\/table>\n<p style=\"margin-left:17%; margin-top: 1em\">This is a subroutine that is called to generate inline code to perform the coercion.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The inline generator is called as a method on the type with one argument. This argument is a <i>string<\/i> containing the variable name to use in the generated code. Typically this is something like &#8216;$_[0]&#8217; or &#8216;$value&#8217;.<\/p>\n<p style=\"margin-left:17%; margin-top: 1em\">The inline generator subroutine should return a <i>string<\/i> of code representing a single term, and it <i>should not<\/i> be terminated with a semicolon. This allows the inlined code to be safely included in an &#8220;if&#8221; statement, for example. You can use &#8220;do { }&#8221; blocks and ternaries to get everything into one term. This single term should evaluate to the new value.<\/p>\n<h2>DECLARATION HELPERS <a name=\"DECLARATION HELPERS\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">This module also exports some helper subs for declaring certain kinds of types:<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>any_isa_type, object_isa_type<\/b> <br \/> The &#8220;any_isa_type&#8221; helper creates a type which accepts a class name or object of the given class. The &#8220;object_isa_type&#8221; helper creates a type which only accepts an object of the given class.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">These subroutines take a type name as the first argument. The remaining arguments are key\/value pairs. Currently this is just the &#8220;class&#8221; key, which should be a class name. This is the class that the type requires.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The type name argument can be omitted to create an anonymous type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">You can also pass just a single argument, in which case that will be used as both the type\u2019s name and the class for the constraint to check.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>any_does_type, object_does_type<\/b> <br \/> The &#8220;any_does_type&#8221; helper creates a type which accepts a class name or object which does the given role. The &#8220;object_does_type&#8221; helper creates a type which only accepts an object which does the given role.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">These subroutines take a type name as the first argument. The remaining arguments are key\/value pairs. Currently this is just the &#8220;role&#8221; key, which should be a role name. This is the class that the type requires.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">This should just work (I hope) with roles created by Moose, Mouse, and Moo (using Role::Tiny).<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The type name argument can be omitted to create an anonymous type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">You can also pass just a single argument, in which case that will be used as both the type\u2019s name and the role for the constraint to check.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>any_can_type, object_can_type<\/b> <br \/> The &#8220;any_can_type&#8221; helper creates a type which accepts a class name or object with the given methods. The &#8220;object_can_type&#8221; helper creates a type which only accepts an object with the given methods.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">These subroutines take a type name as the first argument. The remaining arguments are key\/value pairs. Currently this is just the &#8220;methods&#8221; key, which can be either a string or array reference of strings. These strings are the required methods for the type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The type name argument can be omitted to create an anonymous type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>enum<\/b> <br \/> This creates a type which accepts a string matching a given list of acceptable values.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The first argument is the type name. The remaining arguments are key\/value pairs. Currently this is just the &#8220;values&#8221; key. This should an array reference of acceptable string values.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The type name argument can be omitted to create an anonymous type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>intersection<\/b> <br \/> This creates a type which is the intersection of two or more other types. A union only accepts values which match all of its underlying types.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The first argument is the type name. The remaining arguments are key\/value pairs. Currently this is just the &#8220;of&#8221; key. This should an array reference of types.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The type name argument can be omitted to create an anonymous type.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\"><b>union<\/b> <br \/> This creates a type which is the union of two or more other types. A union accepts any of its underlying types.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The first argument is the type name. The remaining arguments are key\/value pairs. Currently this is just the &#8220;of&#8221; key. This should an array reference of types.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The type name argument can be omitted to create an anonymous type.<\/p>\n<h2>PARAMETERIZED TYPES <a name=\"PARAMETERIZED TYPES\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">You can create a parameterized type by calling &#8220;t&#8221; with additional parameters, like this:<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">my $arrayref_of_int = t( &#8216;ArrayRef&#8217;, of => t(&#8216;Int&#8217;) ); <br \/> my $arrayref_of_hashref_of_int = t( <br \/> &#8216;ArrayRef&#8217;, <br \/> of => t( <br \/> &#8216;HashRef&#8217;, <br \/> of => t(&#8216;Int&#8217;), <br \/> ), <br \/> );<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">The &#8220;t&#8221; subroutine assumes that if it receives more than one argument, it should look up the named type and call &#8220;$type\u2212>parameterize(&#8230;)&#8221; with the additional arguments.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">If the named type cannot be parameterized, it throws an error.<\/p>\n<p style=\"margin-left:11%; margin-top: 1em\">You can also call &#8220;$type\u2212>parameterize&#8221; directly if needed. See Specio::Constraint::Parameterizable for details.<\/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>AUTHOR <a name=\"AUTHOR\"><\/a> <\/h2>\n<p style=\"margin-left:11%; margin-top: 1em\">Dave Rolsky <autarch@urth.org><\/p>\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::Declare \u2212 Specio declaration subroutines <\/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,3255],"class_list":["post-6895","post","type-post","status-publish","format-standard","hentry","category-sin-categoria","tag-man3","tag-speciodeclare"],"gutentor_comment":0,"_links":{"self":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts\/6895","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=6895"}],"version-history":[{"count":0,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/posts\/6895\/revisions"}],"wp:attachment":[{"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/media?parent=6895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/categories?post=6895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lode.uno\/linux-man\/wp-json\/wp\/v2\/tags?post=6895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}