Type::TinyX::Facets - Easily create a facet parameterized Type::Tiny type
version 0.01
package My::Types; use Carp; use Type::Utils; use Type::Library -base, -declare => 'MinMax', 'Bounds', 'Positive'; use Types::Standard -types, 'is_Num'; 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} ); }; facetize qw[min max], declare MinMax, as Num; # 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 ); }; facetize qw[bounds], declare Bounds, as Num; # on-the-fly creation of a facet facetize positive => sub { my ( $o, $var ) = @_; return unless exists $o->{positive}; delete $o->{positive}; sprintf( '%s > 0', $var ); }, qw[ min max ], declare Positive, as Num; 1;
And in some other code:
use My::Types -types; use Type::Params qw[ validate ]; 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
Type::TinyX::Facets make it easy to create parameterized types with facets.
Type::Tiny allows definition of types which can accept parameters:
Type::Tiny
use Types::Standard -types; my $t1 = Array[Int]; my $t2 = Tuple[Int, HashRef];
This defines $t1 as an array of integers. and $t2 as a tuple of two elements, an integer and a hash.
$t1
$t2
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.)
Declare a facet with the given name and code generator. $coderef will be called as
$coderef
$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.
$options
$name
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.
$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} ); };
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
@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;
Facets defined in one package are not available to another package.
The idea and most of the code was lifted from Types::XSD::Lite. Any bugs are definitely mine.
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Type-TinyX-Facets or by email to bug-Type-TinyX-Facets@rt.cpan.org.
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
Diab Jerius <djerius@cpan.org>
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.
To install Type::TinyX::Facets, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Type::TinyX::Facets
CPAN shell
perl -MCPAN -e shell install Type::TinyX::Facets
For more information on module installation, please visit the detailed CPAN module installation guide.