{
    "content": [
        {
            "type": "text",
            "text": "# Specio::Declare (info)\n\n## NAME\n\nSpecio::Declare - Specio declaration subroutines\n\n## SYNOPSIS\n\npackage MyApp::Type::Library;\nuse parent 'Specio::Exporter';\nuse Specio::Declare;\nuse Specio::Library::Builtins;\ndeclare(\n'Foo',\nparent => t('Str'),\nwhere  => sub { $[0] =~ /foo/i },\n);\ndeclare(\n'ArrayRefOfInt',\nparent => t( 'ArrayRef', of => t('Int') ),\n);\nmy $even = anon(\nparent => t('Int'),\ninline => sub {\nmy $type      = shift;\nmy $valuevar = shift;\nreturn $valuevar . ' % 2 == 0';\n},\n);\ncoerce(\nt('ArrayRef'),\nfrom  => t('Foo'),\nusing => sub { [ $[0] ] },\n);\ncoerce(\n$even,\nfrom  => t('Int'),\nusing => sub { $[0] % 2 ? $[0] + 1 : $[0] },\n);\n# Specio name is DateTime\nanyisatype('DateTime');\n# Specio name is DateTimeObject\nobjectisatype( 'DateTimeObject', class => 'DateTime' );\nanycantype(\n'Duck',\nmethods => [ 'duckwalk', 'quack' ],\n);\nobjectcantype(\n'DuckObject',\nmethods => [ 'duckwalk', 'quack' ],\n);\nenum(\n'Colors',\nvalues => [qw( blue green red )],\n);\nintersection(\n'HashRefAndArrayRef',\nof => [ t('HashRef'), t('ArrayRef') ],\n);\nunion(\n'IntOrArrayRef',\nof => [ t('Int'), t('ArrayRef') ],\n);\n\n## DESCRIPTION\n\nThis package exports a set of type declaration helpers. Importing this\npackage also causes it to create a \"t\" subroutine the caller.\n\n## Sections\n\n- **Specio::Declare(3pm)  User Contributed Perl Documentation Specio::Declare(3pm)**\n- **NAME**\n- **VERSION**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **SUBROUTINES**\n- **DECLARATION HELPERS**\n- **PARAMETERIZED TYPES**\n- **SUPPORT**\n- **SOURCE**\n- **AUTHOR**\n- **COPYRIGHT AND LICENSE**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "Specio::Declare",
        "section": "",
        "mode": "info",
        "summary": "Specio::Declare - Specio declaration subroutines",
        "synopsis": "package MyApp::Type::Library;\nuse parent 'Specio::Exporter';\nuse Specio::Declare;\nuse Specio::Library::Builtins;\ndeclare(\n'Foo',\nparent => t('Str'),\nwhere  => sub { $[0] =~ /foo/i },\n);\ndeclare(\n'ArrayRefOfInt',\nparent => t( 'ArrayRef', of => t('Int') ),\n);\nmy $even = anon(\nparent => t('Int'),\ninline => sub {\nmy $type      = shift;\nmy $valuevar = shift;\nreturn $valuevar . ' % 2 == 0';\n},\n);\ncoerce(\nt('ArrayRef'),\nfrom  => t('Foo'),\nusing => sub { [ $[0] ] },\n);\ncoerce(\n$even,\nfrom  => t('Int'),\nusing => sub { $[0] % 2 ? $[0] + 1 : $[0] },\n);\n# Specio name is DateTime\nanyisatype('DateTime');\n# Specio name is DateTimeObject\nobjectisatype( 'DateTimeObject', class => 'DateTime' );\nanycantype(\n'Duck',\nmethods => [ 'duckwalk', 'quack' ],\n);\nobjectcantype(\n'DuckObject',\nmethods => [ 'duckwalk', 'quack' ],\n);\nenum(\n'Colors',\nvalues => [qw( blue green red )],\n);\nintersection(\n'HashRefAndArrayRef',\nof => [ t('HashRef'), t('ArrayRef') ],\n);\nunion(\n'IntOrArrayRef',\nof => [ t('Int'), t('ArrayRef') ],\n);",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "Specio::Declare(3pm)  User Contributed Perl Documentation Specio::Declare(3pm)",
                "lines": 1,
                "subsections": []
            },
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "VERSION",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 71,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "SUBROUTINES",
                "lines": 130,
                "subsections": []
            },
            {
                "name": "DECLARATION HELPERS",
                "lines": 77,
                "subsections": []
            },
            {
                "name": "PARAMETERIZED TYPES",
                "lines": 22,
                "subsections": []
            },
            {
                "name": "SUPPORT",
                "lines": 5,
                "subsections": []
            },
            {
                "name": "SOURCE",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "AUTHOR",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "COPYRIGHT AND LICENSE",
                "lines": 10,
                "subsections": []
            }
        ],
        "sections": {
            "Specio::Declare(3pm)  User Contributed Perl Documentation Specio::Declare(3pm)": {
                "content": "",
                "subsections": []
            },
            "NAME": {
                "content": "Specio::Declare - Specio declaration subroutines\n",
                "subsections": []
            },
            "VERSION": {
                "content": "version 0.47\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "package MyApp::Type::Library;\n\nuse parent 'Specio::Exporter';\n\nuse Specio::Declare;\nuse Specio::Library::Builtins;\n\ndeclare(\n'Foo',\nparent => t('Str'),\nwhere  => sub { $[0] =~ /foo/i },\n);\n\ndeclare(\n'ArrayRefOfInt',\nparent => t( 'ArrayRef', of => t('Int') ),\n);\n\nmy $even = anon(\nparent => t('Int'),\ninline => sub {\nmy $type      = shift;\nmy $valuevar = shift;\n\nreturn $valuevar . ' % 2 == 0';\n},\n);\n\ncoerce(\nt('ArrayRef'),\nfrom  => t('Foo'),\nusing => sub { [ $[0] ] },\n);\n\ncoerce(\n$even,\nfrom  => t('Int'),\nusing => sub { $[0] % 2 ? $[0] + 1 : $[0] },\n);\n\n# Specio name is DateTime\nanyisatype('DateTime');\n\n# Specio name is DateTimeObject\nobjectisatype( 'DateTimeObject', class => 'DateTime' );\n\nanycantype(\n'Duck',\nmethods => [ 'duckwalk', 'quack' ],\n);\n\nobjectcantype(\n'DuckObject',\nmethods => [ 'duckwalk', 'quack' ],\n);\n\nenum(\n'Colors',\nvalues => [qw( blue green red )],\n);\n\nintersection(\n'HashRefAndArrayRef',\nof => [ t('HashRef'), t('ArrayRef') ],\n);\n\nunion(\n'IntOrArrayRef',\nof => [ t('Int'), t('ArrayRef') ],\n);\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "This package exports a set of type declaration helpers. Importing this\npackage also causes it to create a \"t\" subroutine the caller.\n",
                "subsections": []
            },
            "SUBROUTINES": {
                "content": "This module exports the following subroutines.\n\nt('name')\nThis subroutine lets you access any types you have declared so far, as\nwell as any types you imported from another type library.\n\nIf you pass an unknown name, it throws an exception.\n\ndeclare(...)\nThis subroutine declares a named type. The first argument is the type\nname, followed by a set of key/value parameters:\n\no   parent => $type\n\nThe parent should be another type object. Specifically, it can be\nanything which does the Specio::Constraint::Role::Interface role.\nThe parent can be a named or anonymous type.\n\no   where => sub { ... }\n\nThis is a subroutine which defines the type constraint. It will be\npassed a single argument, the value to check, and it should return\ntrue or false to indicate whether or not the value is valid for the\ntype.\n\nThis parameter is mutually exclusive with the \"inline\" parameter.\n\no   inline => sub { ... }\n\nThis is a subroutine that is called to generate inline code to\nvalidate the type. Inlining can be much faster than simply\nproviding a subroutine with the \"where\" parameter, but is often\nmore complicated to get right.\n\nThe inline generator is called as a method on the type with one\nargument. This argument is a string containing the variable name to\nuse in the generated code. Typically this is something like '$[0]'\nor '$value'.\n\nThe inline generator subroutine should return a string of code\nrepresenting a single term, and it should not be terminated with a\nsemicolon. This allows the inlined code to be safely included in an\n\"if\" statement, for example. You can use \"do { }\" blocks and\nternaries to get everything into one term. Do not assign to the\nvariable you are testing. This single term should evaluate to true\nor false.\n\nThe inline generator is expected to include code to implement both\nthe current type and all its parents. Typically, the easiest way to\ndo this is to write a subroutine something like this:\n\nsub {\nmy $self = shift;\nmy $var  = shift;\n\nreturn $self->parent->inlinecheck($var)\n. ' and more checking code goes here';\n}\n\nOr, more concisely:\n\nsub { $[0]->parent->inlinecheck( $[1] ) . 'more code that checks $[1]' }\n\nThe \"inline\" parameter is mutually exclusive with the \"where\"\nparameter.\n\no   messagegenerator => sub { ... }\n\nA subroutine to generate an error message when the type check\nfails. The default message says something like \"Validation failed\nfor type named Int declared in package Specio::Library::Builtins\n(.../Specio/blib/lib/Specio/Library/Builtins.pm) at line 147 in sub\nnamed (eval) with value 1.1\".\n\nYou can override this to provide something more specific about the\nway the type failed.\n\nThe subroutine you provide will be called as a method on the type\nwith two arguments. The first is the description of the type (the\nbit in the message above that starts with \"type named Int ...\" and\nends with \"... in sub named (eval)\". This description says what the\nthing is and where it was defined.\n\nThe second argument is the value that failed the type check, after\nany coercions that might have been applied.\n\nanon(...)\nThis subroutine declares an anonymous type. It is identical to\n\"declare\" except that it expects a list of key/value parameters without\na type name as the first parameter.\n\ncoerce(...)\nThis declares a coercion from one type to another. The first argument\nshould be an object which does the Specio::Constraint::Role::Interface\nrole. This can be either a named or anonymous type. This type is the\ntype that the coercion is to.\n\nThe remaining arguments are key/value parameters:\n\no   from => $type\n\nThis must be an object which does the\nSpecio::Constraint::Role::Interface role. This is type that we are\ncoercing from. Again, this can be either a named or anonymous type.\n\no   using => sub { ... }\n\nThis is a subroutine which defines the type coercion. It will be\npassed a single argument, the value to coerce. It should return a\nnew value of the type this coercion is to.\n\nThis parameter is mutually exclusive with the \"inline\" parameter.\n\no   inline => sub { ... }\n\nThis is a subroutine that is called to generate inline code to\nperform the coercion.\n\nThe inline generator is called as a method on the type with one\nargument. This argument is a string containing the variable name to\nuse in the generated code. Typically this is something like '$[0]'\nor '$value'.\n\nThe inline generator subroutine should return a string of code\nrepresenting a single term, and it should not be terminated with a\nsemicolon. This allows the inlined code to be safely included in an\n\"if\" statement, for example. You can use \"do { }\" blocks and\nternaries to get everything into one term. This single term should\nevaluate to the new value.\n",
                "subsections": []
            },
            "DECLARATION HELPERS": {
                "content": "This module also exports some helper subs for declaring certain kinds\nof types:\n\nanyisatype, objectisatype\nThe \"anyisatype\" helper creates a type which accepts a class name or\nobject of the given class. The \"objectisatype\" helper creates a type\nwhich only accepts an object of the given class.\n\nThese subroutines take a type name as the first argument. The remaining\narguments are key/value pairs. Currently this is just the \"class\" key,\nwhich should be a class name. This is the class that the type requires.\n\nThe type name argument can be omitted to create an anonymous type.\n\nYou can also pass just a single argument, in which case that will be\nused as both the type's name and the class for the constraint to check.\n\nanydoestype, objectdoestype\nThe \"anydoestype\" helper creates a type which accepts a class name or\nobject which does the given role. The \"objectdoestype\" helper creates\na type which only accepts an object which does the given role.\n\nThese subroutines take a type name as the first argument. The remaining\narguments are key/value pairs. Currently this is just the \"role\" key,\nwhich should be a role name. This is the class that the type requires.\n\nThis should just work (I hope) with roles created by Moose, Mouse, and\nMoo (using Role::Tiny).\n\nThe type name argument can be omitted to create an anonymous type.\n\nYou can also pass just a single argument, in which case that will be\nused as both the type's name and the role for the constraint to check.\n\nanycantype, objectcantype\nThe \"anycantype\" helper creates a type which accepts a class name or\nobject with the given methods. The \"objectcantype\" helper creates a\ntype which only accepts an object with the given methods.\n\nThese subroutines take a type name as the first argument. The remaining\narguments are key/value pairs. Currently this is just the \"methods\"\nkey, which can be either a string or array reference of strings. These\nstrings are the required methods for the type.\n\nThe type name argument can be omitted to create an anonymous type.\n\nenum\nThis creates a type which accepts a string matching a given list of\nacceptable values.\n\nThe first argument is the type name. The remaining arguments are\nkey/value pairs. Currently this is just the \"values\" key. This should\nan array reference of acceptable string values.\n\nThe type name argument can be omitted to create an anonymous type.\n\nintersection\nThis creates a type which is the intersection of two or more other\ntypes. A union only accepts values which match all of its underlying\ntypes.\n\nThe first argument is the type name. The remaining arguments are\nkey/value pairs. Currently this is just the \"of\" key. This should an\narray reference of types.\n\nThe type name argument can be omitted to create an anonymous type.\n\nunion\nThis creates a type which is the union of two or more other types. A\nunion accepts any of its underlying types.\n\nThe first argument is the type name. The remaining arguments are\nkey/value pairs. Currently this is just the \"of\" key. This should an\narray reference of types.\n\nThe type name argument can be omitted to create an anonymous type.\n",
                "subsections": []
            },
            "PARAMETERIZED TYPES": {
                "content": "You can create a parameterized type by calling \"t\" with additional\nparameters, like this:\n\nmy $arrayrefofint = t( 'ArrayRef', of => t('Int') );\n\nmy $arrayrefofhashrefofint = t(\n'ArrayRef',\nof => t(\n'HashRef',\nof => t('Int'),\n),\n);\n\nThe \"t\" subroutine assumes that if it receives more than one argument,\nit should look up the named type and call \"$type->parameterize(...)\"\nwith the additional arguments.\n\nIf the named type cannot be parameterized, it throws an error.\n\nYou can also call \"$type->parameterize\" directly if needed. See\nSpecio::Constraint::Parameterizable for details.\n",
                "subsections": []
            },
            "SUPPORT": {
                "content": "Bugs may be submitted at\n<https://github.com/houseabsolute/Specio/issues>.\n\nI am also usually active on IRC as 'autarch' on \"irc://irc.perl.org\".\n",
                "subsections": []
            },
            "SOURCE": {
                "content": "The source code repository for Specio can be found at\n<https://github.com/houseabsolute/Specio>.\n",
                "subsections": []
            },
            "AUTHOR": {
                "content": "Dave Rolsky <autarch@urth.org>\n",
                "subsections": []
            },
            "COPYRIGHT AND LICENSE": {
                "content": "This software is Copyright (c) 2012 - 2021 by Dave Rolsky.\n\nThis is free software, licensed under:\n\nThe Artistic License 2.0 (GPL Compatible)\n\nThe full text of the license can be found in the LICENSE file included\nwith this distribution.\n\nperl v5.32.0                      2021-01-31              Specio::Declare(3pm)",
                "subsections": []
            }
        }
    }
}