| 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
|
|
|
|
|
|
|
|