【发布时间】:2017-02-28 19:45:03
【问题描述】:
我想根据字符串创建一个类型,该类型将具有长度上限,并且 - 可选地 - 长度下限。即参数化类型,其中长度范围将是一个参数。
我想要的实现:
- 字符串长度范围的单独类型。
- 不使用 MooseX::Types::Parameterizable
- 使用 arrayref 直接参数化类型的糖,而不是 hashref:
- 这个:
isa=>Varchar[1, 15] - 不是这个:
isa=>Varchar[{min=>1, max=>15,}]
- 这个:
这就是我目前所拥有的:
文件 MyTypesTiny.pm
package 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
#!/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:
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 是一种类型 - 一个名称标记集合的约束和强制规则。它不对应于对象本身。类型的对象是在创建类属性时创建的,但我这里没有任何类在起作用。
【问题讨论】:
-
你不会放弃吧? :D
-
我看不到
VarcharRange和Varchar之间的联系。 -
查看
Varchar代码中的注释行。本质上,当我通过 ArrayRef 参数化Varchar时,实际上,我想通过VarcharRange参数化Varchar(可以从 ArrayRef 强制)。 -
然后呢?您只想验证字符串是否在该长度范围内?
-
嗯,这些类型不是类。它们是类型。