Aion
view release on metacpan or search on metacpan
lib/Aion/Types.pm view on Meta::CPAN
subtype "Bytes[n]", as Range([]),
init_where {
my $_8bits = A < 8? 8: _8BITS;
my $N = 1 << ($_8bits * A - 1);
SELF->{as} = Range([-$N, $N-1]);
};
subtype "PositiveBytes[n]", as Range([]),
init_where {
my $_8bits = A < 8? 8: _8BITS;
my $M = 1 << ($_8bits*A);
SELF->{as} = Range([0, $M-1]);
};
coerce &Str => from &Undef => via { "" };
coerce &Int => from &Num => via { int($_+($_ < 0? -.5: .5)) };
coerce &Bool => from &Any => via { !!$_ };
subtype 'Join[separator]', as &Str;
coerce &Join, from &ArrayRef, via { join A, @$_ };
subtype 'Split[separator]', as &ArrayRef;
coerce &Split, from &Str, via { [split A, $_] };
coerce &Rat => from &StrRat => via { Math::BigRat->new($_) };
subtype "PositiveNum", as &Num & Range([0, 'Inf']);
subtype "PositiveInt", as &Int & Range([0, 'Inf']);
subtype "Nat", as &Int & Range([1, 'Inf']);
my $_none = ~&Any;
sub None() { $_none }
};
$_->keyfn(\&Aion::Type::typed_sorted_args_key) for Union[], Intersection[];
(Enum[])->keyfn(\&Aion::Type::sorted_args_key);
%Aion::Type::range_lbound = map { (Scalar::Util::refaddr $_->{coerce} => $_->{name} eq 'Range'? '-Inf': 0) } Range[], Lim[], LimKeys[], Len[];
1;
__END__
=encoding utf-8
=head1 NAME
Aion::Types - a library of standard validators and it is used to create new validators
=head1 SYNOPSIS
use Aion::Types;
BEGIN {
subtype SpeakOfKitty => as StrMatch[qr/\bkitty\b/i],
message { "Speak is'nt included kitty!" };
}
"Kitty!" ~~ SpeakOfKitty # -> 1
"abc" ~~ SpeakOfKitty # -> ""
SpeakOfKitty->validate("abc", "This") # @-> Speak is'nt included kitty!
BEGIN {
subtype 'IntOrArrayRef[len, B]',
as Int & Range[5, A]
| ArrayRef[B & Len[A]];
}
35 ~~ IntOrArrayRef[35, Tel] # -> 1
35 ~~ IntOrArrayRef[34, Tel] # -> ""
'+23456789' ~~ Tel # -> 1
'+234567890' ~~ Tel # -> 1
'+23456789' ~~ (Tel & Len[9]) # -> 1
'+234567890' ~~ (Tel & Len[9]) # -> ""
['+23456789', '+23456789'] ~~ IntOrArrayRef[9, Tel] # -> 1
['+234567890', '+23456789'] ~~ IntOrArrayRef[9, Tel] # -> ""
"" ~~ IntOrArrayRef[8, Tel] # -> ""
coerce IntOrArrayRef[35, Str], from Num, via { int($_ + .5) };
IntOrArrayRef([35, Str])->coerce(5.5) # => 6
5.5 >> IntOrArrayRef[35, Str] # => 6
(Tel & Len[9]) < (Tel & Len[10]) # => 1
=head1 DESCRIPTION
This module exports routines:
=over
=item * C<subtype>, C<as>, C<init_where>, C<where>, C<awhere>, C<message> - for creating validators.
=item * C<SELF>, C<ARGS>, C<A>, C<B>, C<C>, C<D>, C<M>, C<N> - for use in validators of a type and its arguments.
=item * C<coerce>, C<from>, C<via> - to create a value converter from one class to another.
=back
Validator hierarchy:
Any
Control
Union[A, B...]
Intersection[A, B...]
Exclude[A...]
Option[A]
Wantarray[A, B]
Item
External[type]
Bool
BoolLike
Enum[e...]
Maybe[A]
Undef
lib/Aion/Types.pm view on Meta::CPAN
PositiveInt
Nat
Ref
Tied`[class]
LValueRef
FormatRef
CodeRef
NamedCode[subname]
ProtoCode[prototype]
ForwardRef
ImplementRef
Isa[A...]
RegexpRef
ValueRef`[A]
ScalarRef`[A]
RefRef`[A]
GlobRef
FileHandle
ArrayRef`[A]
Tuple[A...]
CycleTuple[A...]
HashRef`[A]
Map[A => B]
Dict[k => A, ...]
Object`[class]
Me
Rat
RegexpLike
CodeLike
ArrayLike`[A]
Lim[from?, to]
HashLike`[A]
HasProp[p...]
LimKeys[from?, to]
Like
HasMethods[m...]
Overload`[m...]
InstanceOf[class...]
ConsumerOf[role...]
StrLike
Len[from?, to]
NumLike
Range[from, to]
Float
Double
Bytes[n]
PositiveBytes[n]
=head1 SUBROUTINES
=head2 subtype ($name, @paraphernalia)
Creates a new type.
BEGIN {
subtype One => where { $_ == 1 } message { "Actual 1 only!" };
}
1 ~~ One # -> 1
0 ~~ One # -> ""
eval { One->validate(0) }; $@ # ~> Actual 1 only!
C<where> and C<message> are syntactic sugar, and C<subtype> can be used without them.
BEGIN {
subtype Many => (where => sub { $_ > 1 });
}
2 ~~ Many # -> 1
eval { subtype Many => (where1 => sub { $_ > 1 }) }; $@ # ~> subtype Many unused keys left: where1
eval { subtype 'Many' }; $@ # ~> subtype Many: main::Many exists!
=head2 as ($super_type)
Used with C<subtype> to extend the created C<$super_type> type.
C<as> can accept type expressions combined with set-theoretic operators. It also allows the parameters C<A>, C<B>, C<C>, C<D>, C<ARGS>, C<SELF>, C<M> and C<N>. C<M> and C<N> can be set in the C<init_where> section of the parameterized types included ...
BEGIN {
subtype 'Top[to]', as Range[0, A];
}
+3.0 ~~ Top[3] # -> 1
+3.1 ~~ Top[3] # -> ""
+0.0 ~~ Top[3] # -> 1
-0.1 ~~ Top[3] # -> ""
BEGIN {
subtype 'RedColor', as Enum['red'];
subtype 'BlueColor', as Enum['blue'];
}
BEGIN {
subtype 'RedBlue', as RedColor | BlueColor;
}
'red' ~~ RedBlue # -> 1
'blue' ~~ RedBlue # -> 1
'green' ~~ RedBlue # -> ""
BEGIN {
subtype 'RedBlueOther[colors...]', as ~RedBlue & Enum[ARGS];
}
'red' ~~ RedBlueOther['red'] # -> ""
'green' ~~ RedBlueOther['red', 'green'] # -> 1
=head2 init_where ($code)
Initializes a type with new arguments. Used with C<subtype>.
Initialization is lazy. This means that it will work in the C<test> method or similar.
BEGIN {
subtype 'LessThen[n]',
init_where { Num->validate(A, "Argument LessThen[n]") }
where { $_ < A };
}
eval { LessThen["string"] }; $@ # ^=> Argument LessThen[n]
5 ~~ LessThen[5] # -> ""
=head2 where ($code)
Uses C<$code> as a test. The value for the test is passed to C<$_>.
BEGIN {
subtype 'Two',
where { $_ == 2 };
}
2 ~~ Two # -> 1
3 ~~ Two # -> ""
=head2 awhere ($code)
Used with C<subtype>.
If the type can be with or without arguments, then it is used to check the set with arguments, and C<where> - without.
BEGIN {
subtype 'GreatThen`[num]',
where { $_ > 0 }
awhere { $_ > A }
;
}
0 ~~ GreatThen # -> ""
1 ~~ GreatThen # -> 1
3 ~~ GreatThen[3] # -> ""
4 ~~ GreatThen[3] # -> 1
Required if arguments are optional.
subtype 'Ex`[a]', where {} # @-> subtype Ex`[a]: needs an awhere
subtype 'Ex', awhere {} # @-> subtype Ex: awhere is excess
BEGIN {
subtype 'MyEnum`[item...]',
as Str,
awhere { $_ ~~ scalar ARGS }
;
}
"ab" ~~ MyEnum[qw/ab cd/] # -> 1
=head2 SELF
Current type. C<SELF> is used in C<init_where>, C<where> and C<awhere>.
=head2 ARGS
Arguments of the current type. In a scalar context, it returns a reference to an array, and in an array context, it returns a list. Used in C<init_where>, C<where> and C<awhere>.
lib/Aion/Types.pm view on Meta::CPAN
sub code_ex { ... }
\&code_ex ~~ NamedCode['main::code_ex'] # -> 1
\&code_ex ~~ NamedCode['code_ex'] # -> ""
\&code_ex ~~ NamedCode[qr/_/] # -> 1
=head2 ProtoCode[prototype]
A subroutine with the specified prototype.
sub codex ($;$);
\&codex ~~ ProtoCode['@'] # -> ""
\&codex ~~ ProtoCode['$;$'] # -> 1
\&codex ~~ ProtoCode[qr/^\$/] # -> 1
=head2 ForwardRef
Subroutine without body.
sub code_ref {};
sub code_forward;
\&code_forward ~~ ForwardRef # -> 1
\&code_ref ~~ ForwardRef # -> ""
A subroutine without a body is usually used for pre-declaration, but XS functions also have no body:
\&UNIVERSAL::isa ~~ ForwardRef # -> 1
Calling an undeclared function using C<\&> creates a reference to the previously declared function:
main->can('nouname') ~~ ForwardRef # -> ""
\&nouname ~~ ForwardRef # -> 1
main->can('nouname') ~~ ForwardRef # -> 1
=head2 ImplementRef
Subroutine with body.
sub code_ref {};
sub code_forward;
\&code_ref ~~ ImplementRef # -> 1
\&code_forward ~~ ImplementRef # -> ""
=head2 Isa[A...]
A link to a subroutine with the corresponding signature.
sub sig_ex :Isa(Aion => Int => Str) {}
\&sig_ex ~~ Isa[Aion => Int => Str] # -> 1
\&sig_ex ~~ Isa[Object['Aion'] => Int => Str] # -> 1
\&sig_ex ~~ Isa[Aion => Str => Num] # -> ""
\&sig_ex ~~ Isa[Int => Num] # -> ""
Subroutines without a body are not wrapped in a signature handler, and the signature is remembered to validate the conformity of a subsequently declared subroutine with a body. Therefore the function has no signature.
sub unreachable_sig_ex :Isa(Int => Str);
\&unreachable_sig_ex ~~ Isa[Int => Str] # -> ""
=head2 RegexpRef
Regular expression.
qr// ~~ RegexpRef # -> 1
\1 ~~ RegexpRef # -> ""
=head2 ValueRef`[A]
A reference to a scalar or reference.
\12 ~~ ValueRef # -> 1
\12 ~~ ValueRef # -> 1
\-1.2 ~~ ValueRef[Num] # -> 1
\\-1.2 ~~ ValueRef[ValueRef[Num]] # -> 1
=head2 ScalarRef`[A]
Reference to a scalar.
\12 ~~ ScalarRef # -> 1
\\12 ~~ ScalarRef # -> ""
\-1.2 ~~ ScalarRef[Num] # -> 1
=head2 RefRef`[A]
Link to link.
\12 ~~ RefRef # -> ""
\\12 ~~ RefRef # -> 1
\-1.2 ~~ RefRef[Num] # -> ""
\\-1.2 ~~ RefRef[ScalarRef[Num]] # -> 1
=head2 GlobRef
Link to global
\*A::a ~~ GlobRef # -> 1
*A::a ~~ GlobRef # -> ""
=head2 FileHandle
File descriptor.
\*A::a ~~ FileHandle # -> ""
\*STDIN ~~ FileHandle # -> 1
open my $fh, "<", "/dev/null";
$fh ~~ FileHandle # -> 1
close $fh;
opendir my $dh, ".";
$dh ~~ FileHandle # -> 1
closedir $dh;
( run in 2.658 seconds using v1.01-cache-2.11-cpan-d01c6094234 )