NAME
Type::TinyX::Facets - Easily create a facet parameterized Type::Tiny type
VERSION
version 1.3
SYNOPSIS
package
My::Types;
use
Carp;
use
Type::Utils;
use
Type::Library -base,
-declare
=>
'MinMax'
,
'Bounds'
,
'Positive'
;
use
Type::TinyX::Facets;
# independent facets
facet
'min'
,
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{min};
croak(
"argument to 'min' facet must be a number\n"
)
unless
is_Num(
$o
->{min} );
sprintf
(
'%s >= %s'
,
$var
,
delete
$o
->{min} );
};
facet
'max'
,
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{max};
croak(
"argument to 'max' facet must be a number\n"
)
unless
is_Num(
$o
->{max} );
sprintf
(
'%s <= %s'
,
$var
,
delete
$o
->{max} );
};
declare MinMax, as Num, with_facets [
'min'
,
'max'
];
# related facets
facet
bounds
=>
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{max} ||
exists
$o
->{min};
croak(
"constraint fails condition: max >= min\n"
)
if
exists
$o
->{max} &&
exists
$o
->{min} &&
$o
->{max} <
$o
->{min};
my
@code
;
if
(
exists
$o
->{min} ) {
croak(
"argument to 'min' facet must be a number\n"
)
unless
is_Num(
$o
->{min} );
push
@code
,
sprintf
(
'%s >= %s'
,
$var
,
delete
$o
->{min} );
}
if
(
exists
$o
->{max} ) {
croak(
"argument to 'max' facet must be a number\n"
)
unless
is_Num(
$o
->{max} );
push
@code
,
sprintf
(
'%s <= %s'
,
$var
,
delete
$o
->{max} );
}
return
join
(
' and '
,
@code
);
};
declare Bounds, as Num, with_facets [
'bounds'
];
# on-the-fly creation of a facet
declare Positive, as Num, with_facets [
'min'
,
'max'
,
positive
=>
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{positive};
delete
$o
->{positive};
sprintf
(
'%s > 0'
,
$var
);
},
];
1;
And in some other code:
use
My::Types -types;
validate( [5], MinMax [
min
=> 2 ] );
# passes
validate( [5], MinMax [
min
=> 2,
max
=> 6 ] );
# passes
validate( [5], Bounds [
min
=> 2 ] );
# passes
validate( [5], Bounds [
min
=> 2,
max
=> 6 ] );
# passes
validate( [5], Bounds [
min
=> 5,
max
=> 2 ] )
;
# fails to construct as min > max
validate( [0], Positive [
positive
=> 1 ] );
# fails!
validate( [1], Positive [
positive
=> 1 ] );
# passes
DESCRIPTION
Type::TinyX::Facets make it easy to create parameterized types with facets.
Type::Tiny
allows definition of types which can accept parameters:
This defines $t1
as an array of integers. and $t2
as a tuple of two elements, an integer and a hash.
Parameters are passed as a list to the parameterized constraint generation machinery, and there is great freedom in how they may be interpreted.
This module makes it easy to create a parameterized type which takes name - value pairs or,facets. (The terminology is taken from Types::XSD::Lite, to which this module owes its existence.)
Alternate Names
Type::TinyX::Facets uses Exporter::Tiny, so one might correct(!?) the spelling of "facetize" thusly:
SUBROUTINES
facet( $name, $coderef )
Declare a facet with the given name and code generator. $coderef
will be called as
$coderef
->(
$options
,
$name
,
$facet_name
);
where $options
is a hash of the parameters passed to the type, and $name
is the name of the variable to check against.
The code should return if the passed options are of no interest (and thus the facet should not be applied), otherwise it should return a string containing the validation code. It must delete the parameters that it uses from $o
.
For example, to implement a minimum value check:
facet
'min'
,
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{min};
croak(
"argument to 'min' facet must be a number\n"
)
unless
is_Num(
$o
->{min} );
sprintf
(
'%s >= %s'
,
$var
,
delete
$o
->{min} );
};
with_facets
..., with_facets \
@facets
, ...
Add a facet to the type being declared. with_facets
takes an arrayref of one or more facet names or coderefs to apply to the type, e.g.
declare BoundedEvenInt, as Int,
with_facets [
'min'
,
'max'
,
even
=>
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{even};
delete
$o
->{even};
"! ( ${var} % 2 )"
;
},
],
message {
"This failed"
}
;
facetize( @facets, $type )
DEPRECATED. This function currently pokes at "Type::Tiny"'s innards, and future compatibility cannot be guaranteed.
Use "with_facets" instead.
Add the specified facets to the given type. The type should not have any constraints other than through inheritance from a parent type.
@facets
is a list of facets. If a facet was previously created with the "facet" subroutine, only the name (as a string) need be specified. A facet may also be specified as a name, coderef pair, e.g.
@facets
= (
'min'
,
positive
=>
sub
{
my
(
$o
,
$var
) =
@_
;
return
unless
exists
$o
->{positive};
delete
$o
->{positive};
sprintf
(
'%s > 0'
,
$var
);
}
);
Typically facetize is applied directly to a "declare" in Type::Utils statement, e.g.:
facetize
@facets
,
declare T1, as Num;
LIMITATIONS
Facets defined in one package are not available to another package.
THANKS
- TOBYINK
-
The idea and most of the code was lifted from Types::XSD::Lite. Any bugs are definitely mine.
SOURCE
The development version is on GitLab at https://gitlab.com/djerius/type-tinyx-facets.
SUPPORT
Bugs
Please report any bugs or feature requests to or through the web interface at: https://rt.cpan.org/Public/Dist/Display.html?Name=Type-TinyX-Facets
Source
Source is available at
and may be cloned from
AUTHOR
Diab Jerius <djerius@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2017 by Smithsonian Astrophysical Observatory.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.