Commit | Line | Data |
c466e58f |
1 | package Moose::Meta::Attribute::Native::MethodProvider::Array; |
e3c07b19 |
2 | use Moose::Role; |
3 | |
7960bcc0 |
4 | use List::Util; |
5 | use List::MoreUtils; |
6 | |
b6cca0d5 |
7 | our $VERSION = '1.14'; |
e3c07b19 |
8 | $VERSION = eval $VERSION; |
9 | our $AUTHORITY = 'cpan:STEVAN'; |
10 | |
7960bcc0 |
11 | sub reduce : method { |
12 | my ( $attr, $reader, $writer ) = @_; |
13 | return sub { |
14 | my ( $instance, $f ) = @_; |
15 | our ($a, $b); |
16 | List::Util::reduce { $f->($a, $b) } @{ $reader->($instance) }; |
17 | }; |
18 | } |
19 | |
e11fb12c |
20 | sub sort : method { |
21 | my ( $attr, $reader, $writer ) = @_; |
22 | return sub { |
23 | my ( $instance, $predicate ) = @_; |
24 | die "Argument must be a code reference" |
33f819e1 |
25 | if $predicate && ref $predicate ne 'CODE'; |
e11fb12c |
26 | |
27 | if ($predicate) { |
a163f54f |
28 | # Although it would be nice if we could support just using $a and |
29 | # $b like sort already does, using $a or $b once in a package |
30 | # triggers the 'Name "main::a" used only once' warning, and there |
31 | # is no good way to avoid that, since it happens when the file |
32 | # which defines the coderef is compiled, before we even get a |
33 | # chance to see it here. So, we have no real choice but to use |
34 | # normal parameters. --doy |
e11fb12c |
35 | CORE::sort { $predicate->( $a, $b ) } @{ $reader->($instance) }; |
36 | } |
37 | else { |
38 | CORE::sort @{ $reader->($instance) }; |
39 | } |
40 | }; |
41 | } |
42 | |
7960bcc0 |
43 | sub shuffle : method { |
44 | my ( $attr, $reader, $writer ) = @_; |
45 | return sub { |
46 | my ( $instance ) = @_; |
47 | List::Util::shuffle @{ $reader->($instance) }; |
48 | }; |
49 | } |
50 | |
e11fb12c |
51 | sub grep : method { |
52 | my ( $attr, $reader, $writer ) = @_; |
53 | return sub { |
54 | my ( $instance, $predicate ) = @_; |
c9edbf05 |
55 | CORE::grep { $predicate->() } @{ $reader->($instance) }; |
e11fb12c |
56 | }; |
57 | } |
58 | |
7960bcc0 |
59 | sub uniq : method { |
60 | my ( $attr, $reader, $writer ) = @_; |
61 | return sub { |
62 | my ( $instance ) = @_; |
63 | List::MoreUtils::uniq @{ $reader->($instance) }; |
64 | }; |
65 | } |
66 | |
e11fb12c |
67 | sub join : method { |
68 | my ( $attr, $reader, $writer ) = @_; |
69 | return sub { |
70 | my ( $instance, $separator ) = @_; |
71 | join $separator, @{ $reader->($instance) }; |
72 | }; |
73 | } |
74 | |
e3c07b19 |
75 | sub push : method { |
046c8b5e |
76 | my ( $attr, $reader, $writer ) = @_; |
77 | |
78 | if ( |
79 | $attr->has_type_constraint |
80 | && $attr->type_constraint->isa( |
81 | 'Moose::Meta::TypeConstraint::Parameterized') |
33f819e1 |
82 | ) |
83 | { |
84 | my $container_type_constraint = $attr->type_constraint->type_parameter; |
e3c07b19 |
85 | return sub { |
86 | my $instance = CORE::shift; |
87 | $container_type_constraint->check($_) |
33f819e1 |
88 | || confess "Value " |
89 | . ( $_ || 'undef' ) |
90 | . " did not pass container type constraint '$container_type_constraint'" |
91 | foreach @_; |
046c8b5e |
92 | CORE::push @{ $reader->($instance) } => @_; |
e3c07b19 |
93 | }; |
94 | } |
95 | else { |
96 | return sub { |
97 | my $instance = CORE::shift; |
046c8b5e |
98 | CORE::push @{ $reader->($instance) } => @_; |
e3c07b19 |
99 | }; |
100 | } |
101 | } |
102 | |
103 | sub pop : method { |
046c8b5e |
104 | my ( $attr, $reader, $writer ) = @_; |
e3c07b19 |
105 | return sub { |
046c8b5e |
106 | CORE::pop @{ $reader->( $_[0] ) }; |
e3c07b19 |
107 | }; |
108 | } |
109 | |
110 | sub unshift : method { |
046c8b5e |
111 | my ( $attr, $reader, $writer ) = @_; |
112 | if ( |
113 | $attr->has_type_constraint |
114 | && $attr->type_constraint->isa( |
115 | 'Moose::Meta::TypeConstraint::Parameterized') |
33f819e1 |
116 | ) |
117 | { |
118 | my $container_type_constraint = $attr->type_constraint->type_parameter; |
e3c07b19 |
119 | return sub { |
120 | my $instance = CORE::shift; |
121 | $container_type_constraint->check($_) |
33f819e1 |
122 | || confess "Value " |
123 | . ( $_ || 'undef' ) |
124 | . " did not pass container type constraint '$container_type_constraint'" |
125 | foreach @_; |
046c8b5e |
126 | CORE::unshift @{ $reader->($instance) } => @_; |
e3c07b19 |
127 | }; |
128 | } |
129 | else { |
130 | return sub { |
131 | my $instance = CORE::shift; |
046c8b5e |
132 | CORE::unshift @{ $reader->($instance) } => @_; |
e3c07b19 |
133 | }; |
134 | } |
135 | } |
136 | |
137 | sub shift : method { |
046c8b5e |
138 | my ( $attr, $reader, $writer ) = @_; |
e3c07b19 |
139 | return sub { |
046c8b5e |
140 | CORE::shift @{ $reader->( $_[0] ) }; |
e3c07b19 |
141 | }; |
142 | } |
143 | |
144 | sub get : method { |
046c8b5e |
145 | my ( $attr, $reader, $writer ) = @_; |
e3c07b19 |
146 | return sub { |
046c8b5e |
147 | $reader->( $_[0] )->[ $_[1] ]; |
e3c07b19 |
148 | }; |
149 | } |
150 | |
151 | sub set : method { |
046c8b5e |
152 | my ( $attr, $reader, $writer ) = @_; |
153 | if ( |
154 | $attr->has_type_constraint |
155 | && $attr->type_constraint->isa( |
156 | 'Moose::Meta::TypeConstraint::Parameterized') |
33f819e1 |
157 | ) |
158 | { |
159 | my $container_type_constraint = $attr->type_constraint->type_parameter; |
e3c07b19 |
160 | return sub { |
046c8b5e |
161 | ( $container_type_constraint->check( $_[2] ) ) |
33f819e1 |
162 | || confess "Value " |
163 | . ( $_[2] || 'undef' ) |
164 | . " did not pass container type constraint '$container_type_constraint'"; |
046c8b5e |
165 | $reader->( $_[0] )->[ $_[1] ] = $_[2]; |
e3c07b19 |
166 | }; |
167 | } |
168 | else { |
169 | return sub { |
046c8b5e |
170 | $reader->( $_[0] )->[ $_[1] ] = $_[2]; |
e3c07b19 |
171 | }; |
172 | } |
173 | } |
174 | |
175 | sub accessor : method { |
046c8b5e |
176 | my ( $attr, $reader, $writer ) = @_; |
177 | |
178 | if ( |
179 | $attr->has_type_constraint |
180 | && $attr->type_constraint->isa( |
181 | 'Moose::Meta::TypeConstraint::Parameterized') |
33f819e1 |
182 | ) |
183 | { |
184 | my $container_type_constraint = $attr->type_constraint->type_parameter; |
e3c07b19 |
185 | return sub { |
186 | my $self = shift; |
187 | |
046c8b5e |
188 | if ( @_ == 1 ) { # reader |
189 | return $reader->($self)->[ $_[0] ]; |
e3c07b19 |
190 | } |
046c8b5e |
191 | elsif ( @_ == 2 ) { # writer |
192 | ( $container_type_constraint->check( $_[1] ) ) |
33f819e1 |
193 | || confess "Value " |
194 | . ( $_[1] || 'undef' ) |
195 | . " did not pass container type constraint '$container_type_constraint'"; |
046c8b5e |
196 | $reader->($self)->[ $_[0] ] = $_[1]; |
e3c07b19 |
197 | } |
198 | else { |
199 | confess "One or two arguments expected, not " . @_; |
200 | } |
201 | }; |
202 | } |
203 | else { |
204 | return sub { |
205 | my $self = shift; |
206 | |
046c8b5e |
207 | if ( @_ == 1 ) { # reader |
208 | return $reader->($self)->[ $_[0] ]; |
e3c07b19 |
209 | } |
046c8b5e |
210 | elsif ( @_ == 2 ) { # writer |
211 | $reader->($self)->[ $_[0] ] = $_[1]; |
e3c07b19 |
212 | } |
213 | else { |
214 | confess "One or two arguments expected, not " . @_; |
215 | } |
216 | }; |
217 | } |
218 | } |
219 | |
220 | sub clear : method { |
046c8b5e |
221 | my ( $attr, $reader, $writer ) = @_; |
e3c07b19 |
222 | return sub { |
046c8b5e |
223 | @{ $reader->( $_[0] ) } = (); |
e3c07b19 |
224 | }; |
225 | } |
226 | |
227 | sub delete : method { |
046c8b5e |
228 | my ( $attr, $reader, $writer ) = @_; |
e3c07b19 |
229 | return sub { |
046c8b5e |
230 | CORE::splice @{ $reader->( $_[0] ) }, $_[1], 1; |
33f819e1 |
231 | } |
e3c07b19 |
232 | } |
233 | |
234 | sub insert : method { |
046c8b5e |
235 | my ( $attr, $reader, $writer ) = @_; |
236 | if ( |
237 | $attr->has_type_constraint |
238 | && $attr->type_constraint->isa( |
239 | 'Moose::Meta::TypeConstraint::Parameterized') |
33f819e1 |
240 | ) |
241 | { |
242 | my $container_type_constraint = $attr->type_constraint->type_parameter; |
e3c07b19 |
243 | return sub { |
046c8b5e |
244 | ( $container_type_constraint->check( $_[2] ) ) |
33f819e1 |
245 | || confess "Value " |
246 | . ( $_[2] || 'undef' ) |
247 | . " did not pass container type constraint '$container_type_constraint'"; |
046c8b5e |
248 | CORE::splice @{ $reader->( $_[0] ) }, $_[1], 0, $_[2]; |
e3c07b19 |
249 | }; |
250 | } |
251 | else { |
252 | return sub { |
046c8b5e |
253 | CORE::splice @{ $reader->( $_[0] ) }, $_[1], 0, $_[2]; |
e3c07b19 |
254 | }; |
255 | } |
256 | } |
257 | |
258 | sub splice : method { |
046c8b5e |
259 | my ( $attr, $reader, $writer ) = @_; |
260 | if ( |
261 | $attr->has_type_constraint |
262 | && $attr->type_constraint->isa( |
263 | 'Moose::Meta::TypeConstraint::Parameterized') |
33f819e1 |
264 | ) |
265 | { |
266 | my $container_type_constraint = $attr->type_constraint->type_parameter; |
e3c07b19 |
267 | return sub { |
268 | my ( $self, $i, $j, @elems ) = @_; |
046c8b5e |
269 | ( $container_type_constraint->check($_) ) |
33f819e1 |
270 | || confess "Value " |
271 | . ( defined($_) ? $_ : 'undef' ) |
272 | . " did not pass container type constraint '$container_type_constraint'" |
273 | for @elems; |
046c8b5e |
274 | CORE::splice @{ $reader->($self) }, $i, $j, @elems; |
e3c07b19 |
275 | }; |
276 | } |
277 | else { |
278 | return sub { |
279 | my ( $self, $i, $j, @elems ) = @_; |
046c8b5e |
280 | CORE::splice @{ $reader->($self) }, $i, $j, @elems; |
e3c07b19 |
281 | }; |
282 | } |
283 | } |
284 | |
285 | sub sort_in_place : method { |
046c8b5e |
286 | my ( $attr, $reader, $writer ) = @_; |
e3c07b19 |
287 | return sub { |
046c8b5e |
288 | my ( $instance, $predicate ) = @_; |
e3c07b19 |
289 | |
290 | die "Argument must be a code reference" |
33f819e1 |
291 | if $predicate && ref $predicate ne 'CODE'; |
e3c07b19 |
292 | |
293 | my @sorted; |
294 | if ($predicate) { |
33f819e1 |
295 | @sorted = |
296 | CORE::sort { $predicate->( $a, $b ) } @{ $reader->($instance) }; |
e3c07b19 |
297 | } |
298 | else { |
046c8b5e |
299 | @sorted = CORE::sort @{ $reader->($instance) }; |
e3c07b19 |
300 | } |
301 | |
046c8b5e |
302 | $writer->( $instance, \@sorted ); |
e3c07b19 |
303 | }; |
304 | } |
305 | |
7960bcc0 |
306 | sub natatime : method { |
307 | my ( $attr, $reader, $writer ) = @_; |
308 | return sub { |
309 | my ( $instance, $n, $f ) = @_; |
310 | my $it = List::MoreUtils::natatime($n, @{ $reader->($instance) }); |
ee568bbf |
311 | return $it unless $f; |
312 | |
313 | while (my @vals = $it->()) { |
314 | $f->(@vals); |
7960bcc0 |
315 | } |
ee568bbf |
316 | |
317 | return; |
7960bcc0 |
318 | }; |
319 | } |
320 | |
e3c07b19 |
321 | 1; |
322 | |
323 | __END__ |
324 | |
325 | =pod |
326 | |
327 | =head1 NAME |
328 | |
8b09d5c3 |
329 | Moose::Meta::Attribute::Native::MethodProvider::Array - role providing method generators for Array trait |
e3c07b19 |
330 | |
331 | =head1 DESCRIPTION |
332 | |
333 | This is a role which provides the method generators for |
e22d28f2 |
334 | L<Moose::Meta::Attribute::Native::Trait::Array>. Please check there for |
9da49e13 |
335 | documentation on what methods are provided. |
e3c07b19 |
336 | |
337 | =head1 METHODS |
338 | |
339 | =over 4 |
340 | |
341 | =item B<meta> |
342 | |
343 | =back |
344 | |
e3c07b19 |
345 | =head1 BUGS |
346 | |
d4048ef3 |
347 | See L<Moose/BUGS> for details on reporting bugs. |
e3c07b19 |
348 | |
349 | =head1 AUTHOR |
350 | |
351 | Stevan Little E<lt>stevan@iinteractive.comE<gt> |
352 | |
353 | =head1 COPYRIGHT AND LICENSE |
354 | |
355 | Copyright 2007-2009 by Infinity Interactive, Inc. |
356 | |
357 | L<http://www.iinteractive.com> |
358 | |
359 | This library is free software; you can redistribute it and/or modify |
360 | it under the same terms as Perl itself. |
361 | |
362 | =cut |