The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Aion::Type - class of validators

SYNOPSIS

        use Aion::Type;
        
        my $Int = Aion::Type->new(name => "Int", test => sub { /^-?\d+$/ });
        12   ~~ $Int # => 1
        12.1 ~~ $Int # -> ""
        
        my $Char = Aion::Type->new(name => "Char", test => sub { /^.\z/ });
        $Char->include("a")     # => 1
        $Char->exclude("ab")    # => 1
        
        my $IntOrChar = $Int | $Char;
        77   ~~ $IntOrChar # => 1
        "a"  ~~ $IntOrChar # => 1
        "ab" ~~ $IntOrChar # -> ""
        
        my $Digit = $Int & $Char;
        7  ~~ $Digit # => 1
        77 ~~ $Digit # -> ""
        
        "a" ~~ ~$Int; # => 1
        5   ~~ ~$Int; # -> ""
        
        eval { $Int->validate("a", "..Eval..") }; $@    # ~> ..Eval.. must have the type Int. The it is 'a'

DESCRIPTION

This is construct for make any validators.

It using in Aion::Types::subtype.

METHODS

new (%ARGUMENTS)

Constructor.

ARGUMENTS

  • name (Str) — Name of type.

  • args (ArrayRef) — List of type arguments.

  • init (CodeRef) — Initializer for type.

  • test (CodeRef) — Values cheker.

  • a_test (CodeRef) — Values cheker for types with optional arguments.

  • coerce (ArrayRef[Tuple[Aion::Type, CodeRef]]) — Array of pairs: type and via.

stringify

Stringify of object (name with arguments):

        my $Char = Aion::Type->new(name => "Char");
        
        $Char->stringify # => Char
        
        my $Int = Aion::Type->new(
            name => "Int",
            args => [3, 5],
        );
        
        $Int->stringify  #=> Int[3, 5]

Stringify operations:

        ($Int & $Char)->stringify   # => ( Int[3, 5] & Char )
        ($Int | $Char)->stringify   # => ( Int[3, 5] | Char )
        (~$Int)->stringify          # => ~Int[3, 5]

The operations is objects of Aion::Type with special names:

        Aion::Type->new(name => "Exclude", args => [$Int, $Char])->stringify   # => ~( Int[3, 5] | Char )
        Aion::Type->new(name => "Union", args => [$Int, $Char])->stringify   # => ( Int[3, 5] | Char )
        Aion::Type->new(name => "Intersection", args => [$Int, $Char])->stringify   # => ( Int[3, 5] & Char )

test

Testing the $_ belongs to the class.

        my $PositiveInt = Aion::Type->new(
            name => "PositiveInt",
            test => sub { /^\d+$/ },
        );
        
        local $_ = 5;
        $PositiveInt->test  # -> 1
        local $_ = -6;
        $PositiveInt->test  # -> ""

init

Initial the validator.

        my $Range = Aion::Type->new(
            name => "Range",
            args => [3, 5],
            init => sub {
                @{$Aion::Type::SELF}{qw/min max/} = @{$Aion::Type::SELF->{args}};
            },
            test => sub { $Aion::Type::SELF->{min} <= $_ <= $Aion::Type::SELF->{max} },
        );
        
        $Range->init;
        
        3 ~~ $Range  # -> 1
        4 ~~ $Range  # -> 1
        5 ~~ $Range  # -> 1
        
        2 ~~ $Range  # -> ""
        6 ~~ $Range  # -> ""

include ($element)

checks whether the argument belongs to the class.

        my $PositiveInt = Aion::Type->new(
            name => "PositiveInt",
            test => sub { /^\d+$/ },
        );
        
        $PositiveInt->include(5) # -> 1
        $PositiveInt->include(-6) # -> ""

exclude ($element)

Checks that the argument does not belong to the class.

        my $PositiveInt = Aion::Type->new(
            name => "PositiveInt",
            test => sub { /^\d+$/ },
        );
        
        $PositiveInt->exclude(5)  # -> ""
        $PositiveInt->exclude(-6) # -> 1

coerce ($value)

Coerce $value to the type, if coerce from type and function is in $self->{coerce}.

        my $Int = Aion::Type->new(name => "Int", test => sub { /^-?\d+\z/ });
        my $Num = Aion::Type->new(name => "Num", test => sub { /^-?\d+(\.\d+)?\z/ });
        my $Bool = Aion::Type->new(name => "Bool", test => sub { /^(1|0|)\z/ });
        
        push @{$Int->{coerce}}, [$Bool, sub { 0+$_ }];
        push @{$Int->{coerce}}, [$Num, sub { int($_+.5) }];
        
        $Int->coerce(5.5)    # => 6
        $Int->coerce(undef)  # => 0
        $Int->coerce("abc")  # => abc

detail ($element, $feature)

Return message belongs to error.

        my $Int = Aion::Type->new(name => "Int");
        
        $Int->detail(-5, "Feature car") # => Feature car must have the type Int. The it is -5
        
        my $Num = Aion::Type->new(name => "Num", detail => sub {
            my ($val, $name) = @_;
            "Error: $val is'nt $name!"
        });
        
        $Num->detail("x", "car")  # => Error: x is'nt car!

validate ($element, $feature)

It tested $element and throw detail if element is exclude from class.

        my $PositiveInt = Aion::Type->new(
            name => "PositiveInt",
            test => sub { /^\d+$/ },
        );
        
        eval {
            $PositiveInt->validate(-1, "Neg")
        };
        $@   # ~> Neg must have the type PositiveInt. The it is -1

val_to_str ($element)

Translate $val to string.

        Aion::Type->val_to_str([1,2,{x=>6}])   # => [\n    [0] 1,\n    [1] 2,\n    [2] {\n            x   6\n        }\n]

make ($pkg)

It make subroutine without arguments, who return type.

        BEGIN {
            Aion::Type->new(name=>"Rim", test => sub { /^[IVXLCDM]+$/i })->make(__PACKAGE__);
        }
        
        "IX" ~~ Rim     # => 1

Property init won't use with make.

        eval { Aion::Type->new(name=>"Rim", init => sub {...})->make(__PACKAGE__) }; $@ # ~> init_where won't work in Rim

If subroutine make'nt, then died.

        eval { Aion::Type->new(name=>"Rim")->make }; $@ # ~> syntax error

make_arg ($pkg)

It make subroutine with arguments, who return type.

        BEGIN {
            Aion::Type->new(name=>"Len", test => sub {
                $Aion::Type::SELF->{args}[0] <= length($_) <= $Aion::Type::SELF->{args}[1]
            })->make_arg(__PACKAGE__);
        }
        
        "IX" ~~ Len[2,2]    # => 1

If subroutine make'nt, then died.

        eval { Aion::Type->new(name=>"Rim")->make_arg }; $@ # ~> syntax error

make_maybe_arg ($pkg)

It make subroutine with or without arguments, who return type.

        BEGIN {
            Aion::Type->new(
                name => "Enum123",
                test => sub { $_ ~~ [1,2,3] },
                a_test => sub { $_ ~~ $Aion::Type::SELF->{args} },
            )->make_maybe_arg(__PACKAGE__);
        }
        
        3 ~~ Enum123            # -> 1
        3 ~~ Enum123[4,5,6]     # -> ""
        5 ~~ Enum123[4,5,6]     # -> 1

If subroutine make'nt, then died.

        eval { Aion::Type->new(name=>"Rim")->make_maybe_arg }; $@ # ~> syntax error

OPERATORS

&{}

It make the object is callable.

        my $PositiveInt = Aion::Type->new(
            name => "PositiveInt",
            test => sub { /^\d+$/ },
        );
        
        local $_ = 10;
        $PositiveInt->()    # -> 1
        
        $_ = -1;
        $PositiveInt->()    # -> ""

""

Stringify object.

        Aion::Type->new(name => "Int") . ""   # => Int
        
        my $Enum = Aion::Type->new(name => "Enum", args => [qw/A B C/]);
        
        "$Enum" # => Enum['A', 'B', 'C']

$a | $b

It make new type as union of $a and $b.

        my $Int = Aion::Type->new(name => "Int", test => sub { /^-?\d+$/ });
        my $Char = Aion::Type->new(name => "Char", test => sub { /^.\z/ });
        
        my $IntOrChar = $Int | $Char;
        
        77   ~~ $IntOrChar # => 1
        "a"  ~~ $IntOrChar # => 1
        "ab" ~~ $IntOrChar # -> ""

$a & $b

It make new type as intersection of $a and $b.

        my $Int = Aion::Type->new(name => "Int", test => sub { /^-?\d+$/ });
        my $Char = Aion::Type->new(name => "Char", test => sub { /^.\z/ });
        
        my $Digit = $Int & $Char;
        
        7  ~~ $Digit # => 1
        77 ~~ $Digit # -> ""
        "a" ~~ $Digit # -> ""

~ $a

It make exclude type from $a.

        my $Int = Aion::Type->new(name => "Int", test => sub { /^-?\d+$/ });
        
        "a" ~~ ~$Int; # => 1
        5   ~~ ~$Int; # -> ""

AUTHOR

Yaroslav O. Kosmina Lmailto:dart@cpan.org

LICENSE

GPLv3

COPYRIGHT

The Aion::Type module is copyright © 2023 Yaroslav O. Kosmina. Rusland. All rights reserved.