Work in progress on inlining native traits methods.
[gitmo/Moose.git] / lib / Moose / Meta / Attribute / Native / MethodProvider / Array.pm
CommitLineData
c466e58f 1package Moose::Meta::Attribute::Native::MethodProvider::Array;
e3c07b19 2use Moose::Role;
3
7960bcc0 4use List::Util;
5use List::MoreUtils;
6
b6cca0d5 7our $VERSION = '1.14';
e3c07b19 8$VERSION = eval $VERSION;
9our $AUTHORITY = 'cpan:STEVAN';
10
7960bcc0 11sub 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 20sub 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 43sub shuffle : method {
44 my ( $attr, $reader, $writer ) = @_;
45 return sub {
46 my ( $instance ) = @_;
47 List::Util::shuffle @{ $reader->($instance) };
48 };
49}
50
e11fb12c 51sub 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 59sub uniq : method {
60 my ( $attr, $reader, $writer ) = @_;
61 return sub {
62 my ( $instance ) = @_;
63 List::MoreUtils::uniq @{ $reader->($instance) };
64 };
65}
66
e11fb12c 67sub join : method {
68 my ( $attr, $reader, $writer ) = @_;
69 return sub {
70 my ( $instance, $separator ) = @_;
71 join $separator, @{ $reader->($instance) };
72 };
73}
74
e3c07b19 75sub 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
103sub pop : method {
046c8b5e 104 my ( $attr, $reader, $writer ) = @_;
e3c07b19 105 return sub {
046c8b5e 106 CORE::pop @{ $reader->( $_[0] ) };
e3c07b19 107 };
108}
109
110sub 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
137sub shift : method {
046c8b5e 138 my ( $attr, $reader, $writer ) = @_;
e3c07b19 139 return sub {
046c8b5e 140 CORE::shift @{ $reader->( $_[0] ) };
e3c07b19 141 };
142}
143
144sub get : method {
046c8b5e 145 my ( $attr, $reader, $writer ) = @_;
e3c07b19 146 return sub {
046c8b5e 147 $reader->( $_[0] )->[ $_[1] ];
e3c07b19 148 };
149}
150
151sub 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
175sub 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
220sub clear : method {
046c8b5e 221 my ( $attr, $reader, $writer ) = @_;
e3c07b19 222 return sub {
046c8b5e 223 @{ $reader->( $_[0] ) } = ();
e3c07b19 224 };
225}
226
227sub 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
234sub 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
258sub 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
285sub 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 306sub 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 3211;
322
323__END__
324
325=pod
326
327=head1 NAME
328
8b09d5c3 329Moose::Meta::Attribute::Native::MethodProvider::Array - role providing method generators for Array trait
e3c07b19 330
331=head1 DESCRIPTION
332
333This is a role which provides the method generators for
e22d28f2 334L<Moose::Meta::Attribute::Native::Trait::Array>. Please check there for
9da49e13 335documentation 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 347See L<Moose/BUGS> for details on reporting bugs.
e3c07b19 348
349=head1 AUTHOR
350
351Stevan Little E<lt>stevan@iinteractive.comE<gt>
352
353=head1 COPYRIGHT AND LICENSE
354
355Copyright 2007-2009 by Infinity Interactive, Inc.
356
357L<http://www.iinteractive.com>
358
359This library is free software; you can redistribute it and/or modify
360it under the same terms as Perl itself.
361
362=cut