使用Type :: Tiny参数化类型与另一种类型 [英] Parametrizing type with another type using Type::Tiny
问题描述
我想基于字符串创建一个类型,该类型将具有长度上限,并且-可选-长度下限.即参数化类型,其中长度范围将是一个参数.
我想要实现什么:
I want to create a type, based on the string, which will have upper length limit, and - optionally - lower length limit. I.e., parameterized type, where length range would be a parameter.
What I want in my implementation:
- 字符串长度范围的单独类型.
- 不使用MooseX :: Types :: Parameterizable
- 使用arrayref(而不是hashref)直接参数化类型的糖:
- 此:
isa=>Varchar[1, 15]
- 不是这个:
isa=>Varchar[{min=>1, max=>15,}]
- A separate type for string length range.
- Not using MooseX::Types::Parameterizable
- A sugar of parametrizing the type straight with arrayref, NOT hashref:
- This:
isa=>Varchar[1, 15]
- Not this:
isa=>Varchar[{min=>1, max=>15,}]
这是我到目前为止的内容:
文件MyTypesTiny.pm
That's what I have so far:
File MyTypesTiny.pmpackage MyTypesTiny; use strict; use warnings; use Type::Library -base, -declare => qw( VarcharRange Varchar ); use Type::Utils -all; use Types::Standard -types; use MooseX::Types::Common::Numeric qw( PositiveOrZeroInt ); declare VarcharRange, as HashRef [PositiveOrZeroInt], where { return 0 if ( grep { $_ ne 'min' && $_ ne 'max' } keys %{$_} ); return ( $_->{min} <= $_->{max} ) if ( defined $_->{max} && defined $_->{min} ); return 1; }, message { "$_" }; coerce VarcharRange, from ArrayRef [PositiveOrZeroInt], via { my $result; my @keys = qw(min max); foreach my $val ( reverse @$_ ) { my $key = pop @keys // 'bad_range'; $result->{$key} = $val; } return $result; }; 1;
文件test_varchar.pl
File test_varchar.pl
#!/usr/bin/env perl package MyClass; use Moose; use MyTypesTiny qw( VarcharRange ); has 'my_range' => (isa=>VarcharRange, is=>'ro', coerce=>1); package main; use MyClass; my $check = MyClass->new( my_range => [1, 15], # works, as expected # my_range => [1, 0], # fails, as expected # my_range => [0, 1, 2], # fails, as expected );
好的,VarcharRange有效. 现在,我必须添加Varchar本身.这就是我立即卡住的地方:
添加到MyTypesTiny.pm:Ok, VarcharRange works. Now I have to add Varchar itself. And that's where I get stuck instantly:
added to MyTypesTiny.pm:declare Varchar, as Str, where {}, constraint_generator => sub { # here I have @_ which is an ArrayRef # and I want to create a VarcharRange object $range from it # but what exactly should I do? return sub { my $len = length($_); return 0 if ( $range->{min} && $len < $range->{min} ); return 0 if ( $range->{max} && $len > $range->{max} ); return 1; }; };
我的大脑在沸腾.我已经准备好ArrayRef.我需要的是一个用它制成的VarcharRange(基本上是HashRef)对象.但是VarcharRange是一种类型-名称标记一组约束和强制规则.它本身并不对应于对象.类型的对象是在创建类属性时创建的,但这里没有任何类.
My brain is boiling. I have my ArrayRef ready. All I need is a VarcharRange (which is basically a HashRef) object to be made from it. But VarcharRange is a type - a name marking set of constraints and coercion rules. It does not correspond to an object per se. Objects for types are created when class attributes are created, but I don't have any class in play here.
推荐答案
这是一个答案,使您能够为"Varchar"类型提供参数.启用参数化类型的魔术是为该类型提供
constraint_generator
.此解决方案没有中间的hashref,只有一种类型.This is an answer that gives you the ability to give parameters to the "Varchar" type. The magic that enables parameterised types is to provide a
constraint_generator
to the type. This solution does not have the intermediate hashref, and it only has one type.MyTypesTiny.pm:
MyTypesTiny.pm:
package MyTypesTiny; use Types::Standard -all; use Type::Library -base, -declare => qw(Varchar); use Type::Utils -all; sub _get_varchar_args { die "can only give 0-2 parameters" if @_ > 2; map assert_Int($_), @_; return @_ == 1 ? (0, @_) : @_; } declare "Varchar", as Str, constraint_generator => sub { my ($min_length, $max_length) = _get_varchar_args(@_); return sub { length($_) >= $min_length and length($_) <= $max_length; }; }, inline_generator => sub { my ($min_length, $max_length) = _get_varchar_args(@_); return sub { my ($constraint, $varname) = @_; return sprintf( 'length(%s) >= %d and length(%s) <= %d', $varname, $min_length, $varname, $max_length, ); }; }; 1;
MyClass.pm:
MyClass.pm:
package MyClass; use Moo; use MyTypesTiny -all; has my_string => ( is => 'ro', isa => Varchar[9, 10], ); 1;
tester.pl:
tester.pl:
#!perl use MyClass; my $check = MyClass->new( my_string => 'ASDef45F%'); # length 9, ok $check = MyClass->new( my_string => 'f45F%'); # length 5, not ok
这篇关于使用Type :: Tiny参数化类型与另一种类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- This:
- 此: