line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
use 5.008; |
3
|
10
|
|
|
10
|
|
3700721
|
|
|
10
|
|
|
|
|
135
|
|
4
|
|
|
|
|
|
|
our $VERSION = '0.10'; |
5
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Moose::Util::TypeConstraints; |
8
|
10
|
|
|
10
|
|
3787
|
use MooseX::Meta::TypeConstraint::Parameterizable; |
|
10
|
|
|
|
|
1844509
|
|
|
10
|
|
|
|
|
104
|
|
9
|
10
|
|
|
10
|
|
28702
|
use MooseX::Types -declare => [qw(Parameterizable)]; |
|
10
|
|
|
|
|
5584
|
|
|
10
|
|
|
|
|
527
|
|
10
|
10
|
|
|
10
|
|
5026
|
|
|
10
|
|
|
|
|
392834
|
|
|
10
|
|
|
|
|
73
|
|
11
|
|
|
|
|
|
|
Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint( |
12
|
|
|
|
|
|
|
MooseX::Meta::TypeConstraint::Parameterizable->new( |
13
|
|
|
|
|
|
|
name => 'MooseX::Types::Parameterizable::Parameterizable', |
14
|
|
|
|
|
|
|
parent => find_type_constraint('Any'), |
15
|
|
|
|
|
|
|
constraint => sub {1}, |
16
|
|
|
|
|
|
|
) |
17
|
|
|
|
|
|
|
); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
1; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 NAME |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
MooseX::Types::Parameterizable - Create your own Parameterizable Types. |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
The follow is example usage. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
package Test::MooseX::Types::Parameterizable::Synopsis; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
use Moose; |
33
|
|
|
|
|
|
|
use MooseX::Types::Parameterizable qw(Parameterizable); |
34
|
|
|
|
|
|
|
use MooseX::Types::Moose qw(Str Int ArrayRef); |
35
|
|
|
|
|
|
|
use MooseX::Types -declare=>[qw(Varchar)]; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
Create a type constraint that is similar to SQL Varchar type. |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
subtype Varchar, |
40
|
|
|
|
|
|
|
as Parameterizable[Str,Int], |
41
|
|
|
|
|
|
|
where { |
42
|
|
|
|
|
|
|
my($string, $int) = @_; |
43
|
|
|
|
|
|
|
$int >= length($string) ? 1:0; |
44
|
|
|
|
|
|
|
}, |
45
|
|
|
|
|
|
|
message { "'$_[0]' is too long (max length $_[1])" }; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
Coerce an ArrayRef to a string via concatenation. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
coerce Varchar, |
50
|
|
|
|
|
|
|
from ArrayRef, |
51
|
|
|
|
|
|
|
via { |
52
|
|
|
|
|
|
|
my ($arrayref, $int) = @_; |
53
|
|
|
|
|
|
|
join('', @$arrayref); |
54
|
|
|
|
|
|
|
}; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
has 'varchar_five' => (isa=>Varchar[5], is=>'ro', coerce=>1); |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
has 'varchar_ten' => (isa=>Varchar[10], is=>'ro'); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Object created since attributes are valid |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
my $object1 = __PACKAGE__->new( |
63
|
|
|
|
|
|
|
varchar_five => '1234', |
64
|
|
|
|
|
|
|
varchar_ten => '123456789', |
65
|
|
|
|
|
|
|
); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Dies with an invalid constraint for 'varchar_five' |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
my $object2 = __PACKAGE__->new( |
70
|
|
|
|
|
|
|
varchar_five => '12345678', ## too long! |
71
|
|
|
|
|
|
|
varchar_ten => '123456789', |
72
|
|
|
|
|
|
|
); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
varchar_five coerces as expected |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
my $object3 = __PACKAGE__->new( |
77
|
|
|
|
|
|
|
varchar_five => [qw/aa bb/], ## coerces to "aabb" |
78
|
|
|
|
|
|
|
varchar_ten => '123456789', |
79
|
|
|
|
|
|
|
); |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
See t/05-pod-examples.t for runnable versions of all POD code |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=head1 VERSION 0.09 RELEASE NOTES |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
In trying to solve a critical incompatibility with newer versions of L<Moose> |
86
|
|
|
|
|
|
|
I've had to increase the minimum L<Moose> and L<MooseX::Types> required |
87
|
|
|
|
|
|
|
versions dramatically. I just had no good option to maintain L<Moose> version |
88
|
|
|
|
|
|
|
back compatibility down to VERSION 1.08 (the version of L<Moose> when I first |
89
|
|
|
|
|
|
|
released this package). Please test carefully before upgrading your production |
90
|
|
|
|
|
|
|
code with this version! |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
Options and code are welcomed to help with this. Thanks! |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
B<Update from 2022>: Its been ten years and we never figured out all these issues that |
95
|
|
|
|
|
|
|
arose from Moose 2.0. I got all the tests to pass except for some issues around |
96
|
|
|
|
|
|
|
parameterized types and coercions. In the interests of not having failed code |
97
|
|
|
|
|
|
|
on CPAN I'm releasing all the modern updates and skipping that one block of tests. |
98
|
|
|
|
|
|
|
However I recommend considering this an interesting proof of concept and building |
99
|
|
|
|
|
|
|
a new implementation from start, probably based on L<Type::Tiny> which also works |
100
|
|
|
|
|
|
|
with L<Moo>. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
As a result I recomend not using this module for new code. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head1 DESCRIPTION |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
A L<MooseX::Types> library for creating parameterizable types. A parameterizable |
107
|
|
|
|
|
|
|
type constraint for all intents and uses is a subclass of a parent type, but |
108
|
|
|
|
|
|
|
adds additional type parameters which are available to constraint callbacks |
109
|
|
|
|
|
|
|
(such as inside the 'where' clause of a type constraint definition) or in the |
110
|
|
|
|
|
|
|
coercions you define for a given type constraint. |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
If you have L<Moose> experience, you probably are familiar with the builtin |
113
|
|
|
|
|
|
|
parameterizable type constraints 'ArrayRef' and 'HashRef'. This type constraint |
114
|
|
|
|
|
|
|
lets you generate your own versions of parameterized constraints that work |
115
|
|
|
|
|
|
|
similarly. See L<Moose::Util::TypeConstraints> for more. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Using this type constraint, you can generate new type constraints that have |
118
|
|
|
|
|
|
|
additional runtime advice, such as being able to specify maximum and minimum |
119
|
|
|
|
|
|
|
values for an Int (integer) type constraint: |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
subtype Range, |
122
|
|
|
|
|
|
|
as Dict[max=>Int, min=>Int], |
123
|
|
|
|
|
|
|
where { |
124
|
|
|
|
|
|
|
my ($range) = @_; |
125
|
|
|
|
|
|
|
return $range->{max} > $range->{min}; |
126
|
|
|
|
|
|
|
}; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
subtype RangedInt, |
129
|
|
|
|
|
|
|
as Parameterizable[Int, Range], |
130
|
|
|
|
|
|
|
where { |
131
|
|
|
|
|
|
|
my ($value, $range) = @_; |
132
|
|
|
|
|
|
|
return ($value >= $range->{min} && |
133
|
|
|
|
|
|
|
$value <= $range->{max}); |
134
|
|
|
|
|
|
|
}, |
135
|
|
|
|
|
|
|
message { |
136
|
|
|
|
|
|
|
my ($value, $range) = @_; |
137
|
|
|
|
|
|
|
return "$value must be between $range->{min} and $range->{max} (inclusive)"; |
138
|
|
|
|
|
|
|
}; |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
RangedInt([{min=>10,max=>100}])->check(50); ## OK |
141
|
|
|
|
|
|
|
RangedInt([{min=>50, max=>75}])->check(99); ## Not OK, exceeds max |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
This is useful since it lets you generate common patterns of type constraints |
144
|
|
|
|
|
|
|
rather than build a custom type constraint for all similar cases. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
The type parameter must be valid against the 'constrainting' type constraint used |
147
|
|
|
|
|
|
|
in the Parameterizable condition. If you pass an invalid value this throws a |
148
|
|
|
|
|
|
|
hard Moose exception. You'll need to capture it in an eval or related exception |
149
|
|
|
|
|
|
|
catching system (see L<TryCatch> or L<Try::Tiny>.) |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
For example the following would throw a hard error (and not just return false) |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range! |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
In the above case the 'min' value is larger than the 'max', which violates the |
156
|
|
|
|
|
|
|
Range constraint. We throw a hard error here since I think incorrect type |
157
|
|
|
|
|
|
|
parameters are most likely to be the result of a typo or other true error |
158
|
|
|
|
|
|
|
conditions. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
If you can't accept a hard exception here, you can either trap it as advised |
161
|
|
|
|
|
|
|
above or you need to test the constraining values first, as in: |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
my $range = {min=>99, max=>10}; |
164
|
|
|
|
|
|
|
if(my $err = Range->validate($range)) { |
165
|
|
|
|
|
|
|
## Handle #$err |
166
|
|
|
|
|
|
|
} else { |
167
|
|
|
|
|
|
|
RangedInt($range)->check(99); |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Please note that for ArrayRef or HashRef parameterizable type constraints, as in the |
171
|
|
|
|
|
|
|
example above, as a convenience we automatically ref the incoming type |
172
|
|
|
|
|
|
|
parameters, so that the above could also be written as: |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
RangedInt([min=>10,max=>100])->check(50); ## OK |
175
|
|
|
|
|
|
|
RangedInt([min=>50, max=>75])->check(99); ## Not OK, exceeds max |
176
|
|
|
|
|
|
|
RangedInt([min=>99, max=>10])->check(10); ## Exception, not valid Range |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
This is the preferred syntax, as it improve readability and adds to the |
179
|
|
|
|
|
|
|
conciseness of your type constraint declarations. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Also note that if you 'chain' parameterization results with a method call like: |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
TypeConstraint([$ob])->method; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
You need to have the "(...)" around the ArrayRef in the Type Constraint |
186
|
|
|
|
|
|
|
parameters. You can skip the wrapping parenthesis in the most common cases, |
187
|
|
|
|
|
|
|
such as when you use the type constraint in the options section of a L<Moose> |
188
|
|
|
|
|
|
|
attribute declaration, or when defining type libraries. |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head2 Subtyping a Parameterizable type constraints |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
When subclassing a parameterizable type you must be careful to match either the |
193
|
|
|
|
|
|
|
required type parameter type constraint, or if re-parameterizing, the new |
194
|
|
|
|
|
|
|
type constraints are a subtype of the parent. For example: |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
subtype RangedInt, |
197
|
|
|
|
|
|
|
as Parameterizable[Int, Range], |
198
|
|
|
|
|
|
|
where { |
199
|
|
|
|
|
|
|
my ($value, $range) = @_; |
200
|
|
|
|
|
|
|
return ($value >= $range->{min} && |
201
|
|
|
|
|
|
|
$value =< $range->{max}); |
202
|
|
|
|
|
|
|
}, |
203
|
|
|
|
|
|
|
message { |
204
|
|
|
|
|
|
|
my ($value, $range) = @_; |
205
|
|
|
|
|
|
|
return "$value must be between $range->{min} and $range->{max} (inclusive)"; |
206
|
|
|
|
|
|
|
}; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Example subtype with additional constraints: |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
subtype PositiveRangedInt, |
211
|
|
|
|
|
|
|
as RangedInt, |
212
|
|
|
|
|
|
|
where { |
213
|
|
|
|
|
|
|
shift >= 0; |
214
|
|
|
|
|
|
|
}; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
In this case you'd now have a parameterizable type constraint which would |
217
|
|
|
|
|
|
|
work like: |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
Test::More::ok PositiveRangedInt([{min=>-10, max=>75}])->check(5); |
220
|
|
|
|
|
|
|
Test::More::ok !PositiveRangedInt([{min=>-10, max=>75}])->check(-5); |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Of course the above is somewhat counter-intuitive to the reader, since we have |
223
|
|
|
|
|
|
|
defined our 'RangedInt' in such as way as to let you declare negative ranges. |
224
|
|
|
|
|
|
|
For the moment each type constraint rule is apply without knowledge of any |
225
|
|
|
|
|
|
|
other rule, nor can a rule 'inform' existing rules. This is a limitation of |
226
|
|
|
|
|
|
|
the current system. However, you could instead do the following: |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
## Subtype of Int for positive numbers |
229
|
|
|
|
|
|
|
subtype PositiveInt, |
230
|
|
|
|
|
|
|
as Int, |
231
|
|
|
|
|
|
|
where { |
232
|
|
|
|
|
|
|
my ($value, $range) = @_; |
233
|
|
|
|
|
|
|
return $value >= 0; |
234
|
|
|
|
|
|
|
}; |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
## subtype Range to re-parameterize Range with subtypes |
237
|
|
|
|
|
|
|
subtype PositiveRange, |
238
|
|
|
|
|
|
|
as Range[max=>PositiveInt, min=>PositiveInt]; |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
## create subtype via reparameterizing |
241
|
|
|
|
|
|
|
subtype PositiveRangedInt, |
242
|
|
|
|
|
|
|
as RangedInt[PositiveRange]; |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
This would constrain values in the same way as the previous type constraint but |
245
|
|
|
|
|
|
|
have the bonus that you'd throw a hard exception if you try to use an incorrect |
246
|
|
|
|
|
|
|
range: |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
Test::More::ok PositiveRangedInt([{min=>10, max=>75}])->check(15); ## OK |
249
|
|
|
|
|
|
|
Test::More::ok !PositiveRangedInt([{min=>-10, max=>75}])->check(-5); ## Dies |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Notice how re-parameterizing the parameterizable type 'RangedInt' works slightly |
252
|
|
|
|
|
|
|
differently from re-parameterizing 'PositiveRange' Although it initially takes |
253
|
|
|
|
|
|
|
two type constraint values to declare a parameterizable type, should you wish to |
254
|
|
|
|
|
|
|
later re-parameterize it, you only use a subtype of the extra type parameter |
255
|
|
|
|
|
|
|
(the parameterizable type constraints) since the first type constraint sets the |
256
|
|
|
|
|
|
|
parent type for the parameterizable type. |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
In other words, given the example above, a type constraint of 'RangedInt' would |
259
|
|
|
|
|
|
|
have a parent of 'Int', not 'Parameterizable' and for all intends and uses you |
260
|
|
|
|
|
|
|
could stick it wherever you'd need an Int. You can't change the parent, even |
261
|
|
|
|
|
|
|
to make it a subclass of Int. |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=head2 Coercions |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
A type coercion is a rule that allows you to transform one type from one or |
266
|
|
|
|
|
|
|
more other types. Please see L<Moose::Cookbook::Basics::Recipe5> for an example |
267
|
|
|
|
|
|
|
of type coercions if you are not familiar with the subject. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
L<MooseX::Types::Parameterizable> supports type coercions in all the ways you |
270
|
|
|
|
|
|
|
would expect. In addition, it also supports a limited form of type coercion |
271
|
|
|
|
|
|
|
inheritance. Generally speaking, type constraints don't inherit coercions since |
272
|
|
|
|
|
|
|
this would rapidly become confusing. However, since your parameterizable type |
273
|
|
|
|
|
|
|
is intended to become parameterized in order to be useful, we support inheriting |
274
|
|
|
|
|
|
|
from a 'base' parameterizable type constraint to its 'child' parameterized sub |
275
|
|
|
|
|
|
|
types. |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
For the purposes of this discussion, a parameterizable type is a subtype created |
278
|
|
|
|
|
|
|
when you say, "as Parameterizable[..." in your sub type declaration. For |
279
|
|
|
|
|
|
|
example: |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
subtype Varchar, |
282
|
|
|
|
|
|
|
as Parameterizable[Str, Int], |
283
|
|
|
|
|
|
|
where { |
284
|
|
|
|
|
|
|
my($string, $int) = @_; |
285
|
|
|
|
|
|
|
$int >= length($string) ? 1:0; |
286
|
|
|
|
|
|
|
}, |
287
|
|
|
|
|
|
|
message { "'$_[0]' is too long (max length $_[1])" }; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
This is the L</SYNOPSIS> example, which creates a new parameterizable subtype of |
290
|
|
|
|
|
|
|
Str which takes a single type parameter which must be an Int. This Int is used |
291
|
|
|
|
|
|
|
to constrain the allowed length of the Str value. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Now, this new sub type, "Varchar", is parameterizable since it can take a type |
294
|
|
|
|
|
|
|
parameter. We can apply some coercions to it: |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
coerce Varchar, |
297
|
|
|
|
|
|
|
from Object, |
298
|
|
|
|
|
|
|
via { "$_" }, ## stringify the object |
299
|
|
|
|
|
|
|
from ArrayRef, |
300
|
|
|
|
|
|
|
via { join '', @$_ }; ## convert array to string |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
This parameterizable subtype, "Varchar" itself is something you'd never use |
303
|
|
|
|
|
|
|
directly to constraint a value. In other words you'd never do something like: |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
has name => (isa=>Varchar, ...); ## Why not just use a Str? |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
You are going to do this: |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
has name => (isa=>Varchar[40], ...) |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
Which is actually useful. However, "Varchar[40]" is a parameterized type, it |
312
|
|
|
|
|
|
|
is a subtype of the parameterizable "Varchar" and it inherits coercions from |
313
|
|
|
|
|
|
|
its parent. This may be a bit surprising to L<Moose> developers, but I believe |
314
|
|
|
|
|
|
|
this is the actual desired behavior. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
You can of course add new coercions to a subtype of a parameterizable type: |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
subtype MySpecialVarchar, |
319
|
|
|
|
|
|
|
as Varchar; |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
coerce MySpecialVarchar, |
322
|
|
|
|
|
|
|
from ... |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
In which case this new parameterizable type would NOT inherit coercions from |
325
|
|
|
|
|
|
|
it's parent parameterizable type (Varchar). This is done in keeping with how |
326
|
|
|
|
|
|
|
generally speaking L<Moose> type constraints avoid complicated coercion inheritance |
327
|
|
|
|
|
|
|
schemes, however I am open to discussion if there are valid use cases. |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
NOTE: One thing you can't do is add a coercion to an already parameterized type. |
330
|
|
|
|
|
|
|
Currently the following would throw a hard error: |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
subtype 40CharStr, |
333
|
|
|
|
|
|
|
as Varchar[40]; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
coerce 40CharStr, ... # BANG! |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
This limitation is enforced since generally we expect coercions on the parent. |
338
|
|
|
|
|
|
|
However if good use cases arise we may lift this in the future. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
In general we are trying to take a conservative approach that keeps in line with |
341
|
|
|
|
|
|
|
how most L<Moose> authors expect type constraints to work. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=head2 Recursion |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
TBD - Needs a use case... Anyone? |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=head1 TYPE CONSTRAINTS |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
This type library defines the following constraints. |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 Parameterizable[ParentTypeConstraint, ConstrainingValueTypeConstraint] |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
Create a subtype of ParentTypeConstraint with a dependency on a value that can |
354
|
|
|
|
|
|
|
pass the ConstrainingValueTypeConstraint. If ConstrainingValueTypeConstraint is empty |
355
|
|
|
|
|
|
|
we default to the 'Any' type constraint (see L<Moose::Util::TypeConstraints>). |
356
|
|
|
|
|
|
|
This is useful if you are creating some base Parameterizable type constraints |
357
|
|
|
|
|
|
|
that you intend to sub class. |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=head1 SEE ALSO |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
The following modules or resources may be of interest. |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
L<Moose>, L<Moose::Meta::TypeConstraint>, L<MooseX::Types> |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head1 AUTHOR |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
John Napiorkowski, C<< <jjnapiork@cpan.org> >> |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
372
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=cut |
375
|
|
|
|
|
|
|
|