gpt4 book ai didi

perl - 使用 Type::Tiny 将类型参数化为另一种类型

转载 作者:行者123 更新时间:2023-12-01 05:15:42 25 4
gpt4 key购买 nike

我想创建一个基于字符串的类型,该类型将具有长度上限和 - 可选 - 长度下限。即,参数化类型,其中长度范围将是一个参数。
在我的实现中我想要什么:

  • 字符串长度范围的单独类型。
  • 不使用 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 是一种类型——一个标记约束和强制规则集的名称。它不对应于一个对象本身。类型的对象是在创建类属性时创建的,但我这里没有任何类在起作用。

最佳答案

这是一个让您能够为“Varchar”类型提供参数的答案。启用参数化类型的神奇之处在于为该类型提供一个 constraint_generator。该方案没有中间hashref,只有一种类型。

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:

package MyClass;

use Moo;
use MyTypesTiny -all;

has my_string => (
is => 'ro',
isa => Varchar[9, 10],
);

1;

测试器.pl:

#!perl
use MyClass;
my $check = MyClass->new( my_string => 'ASDef45F%'); # length 9, ok
$check = MyClass->new( my_string => 'f45F%'); # length 5, not ok

关于perl - 使用 Type::Tiny 将类型参数化为另一种类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42517460/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com