File Coverage

blib/lib/perl5i/2/ARRAY.pm
Criterion Covered Total %
statement 174 174 100.0
branch 67 72 93.0
condition 15 18 83.3
subroutine 48 48 100.0
pod 0 8 0.0
total 304 320 95.0


line stmt bran cond sub pod time code
1             # vi: set ts=4 sw=4 ht=4 et :
2             package perl5i::2::ARRAY;
3 103     103   4253 use 5.010;
  103         327  
  103         5742  
4              
5 103     103   625 use strict;
  103         175  
  103         4446  
6 103     103   726 use warnings;
  103         193  
  103         7136  
7 103     103   141591 no if $] >= 5.018000, warnings => 'experimental::smartmatch';
  103         1095  
  103         680  
8              
9             # Don't accidentally turn carp/croak into methods.
10             require Carp::Fix::1_25;
11              
12 103     103   87198 use perl5i::2::Signatures;
  103         433  
  103         887  
13 103     103   26597 use perl5i::2::autobox;
  103         273  
  103         1243  
14              
15             # A foreach which honors the number of parameters in the signature
16 103     103   18163 method foreach($code) {
  5     5   1188  
  5         9  
17 5         7 my $n = 1;
18 5 100       35 if( my $sig = $code->signature ) {
19 3         24 $n = $sig->num_positional_params;
20 3 50       8 Carp::Fix::1_25::croak("Function passed to foreach takes no arguments") unless $n;
21             }
22              
23 5         10 my $idx = 0;
24 5         7 while ( $idx <= $#{$self} ) {
  17         38  
25 12         22 $code->(@{$self}[$idx..($idx+$n-1)]);
  12         34  
26 12         58 $idx += $n;
27             }
28              
29 5         10 return;
30             }
31              
32 103     103   12352 method first($filter) {
  14     14   8065  
  14         29  
33             # Deep recursion and segfault (lines 90 and 91 in first.t) if we use
34             # the same elegant approach as in grep().
35 14 100       46 if ( ref $filter eq 'Regexp' ) {
36 1     2   8 return List::Util::first( sub { $_ ~~ $filter }, @$self );
  2         19  
37             }
38              
39 13     37   70 return List::Util::first( sub { $filter->() }, @$self );
  37         149  
40              
41             }
42              
43 103     103   13527 method map( $code ) {
  5     5   40  
  5         8  
44 5         15 my @result = CORE::map { $code->($_) } @$self;
  25         89  
45              
46 5 100       92 return wantarray ? @result : \@result;
47             }
48              
49 103     103   12985 method as_hash{
  2     2   1830  
50 2         6 my %result = CORE::map { $_ => 1 } @$self;
  7         21  
51 2 100       14 return wantarray ? %result : \%result;
52             }
53              
54              
55 103     103   18270 method pick ( $num ){
  10     10   11779  
  10         14  
56 10 100       216 Carp::Fix::1_25::croak("pick() takes the number of elements to pick")
57             unless defined $num;
58 9 100 100     61 Carp::Fix::1_25::croak("pick() takes a positive integer or zero, not '$num'")
      66        
59             unless $num->is_integer && ($num->is_positive or $num == 0);
60            
61 7 100       21 if($num >= @$self){
62 3         14 my @result = List::Util::shuffle(@$self);
63 3 50       21 return wantarray ? @result : \@result;
64             }
65            
66             # for the first position in the array, generate a random number that gives
67             # that element an n/N chance of being picked (where n is the number of elements to pick and N is the total array size);
68             # repeat for the rest of the array, each time altering the probability of
69             # the element being picked to reflect the number of elements picked so far and the number left.
70 4         7 my $num_left = @$self;
71 4         6 my @result;
72 4         8 my $i=0;
73 4         10 while($num > 0){
74 20         69 my $rand = int(rand($num_left));
75 20 100       36 if($rand < $num){
76 9         14 push(@result, $self->[$i]);
77 9         14 $num--;
78             }
79 20         21 $num_left--;
80 20         38 $i++;
81             }
82              
83             # Don't return the picks in the same order as the original array
84             # Simulates what would happen if you shuffled first
85 4         34 @result = @result->shuffle;
86              
87 4 50       310 return wantarray ? @result : \@result;
88             }
89              
90              
91 103     103   14139 method pick_one() {
  3     3   1716  
92 3         13 return @$self[int rand @$self];
93             }
94              
95              
96 103     103   12557 method grep($filter) {
  14     14   82712  
  14         22  
97 14         30 my @result = CORE::grep { $_ ~~ $filter } @$self;
  46         188  
98              
99 14 100       161 return wantarray ? @result : \@result;
100             }
101              
102 103     103   14571 method popn($times) {
  7     7   9506  
  7         14  
103 7 100       238 Carp::Fix::1_25::croak("popn() takes the number of elements to pop")
104             unless defined $times;
105 6 100 100     46 Carp::Fix::1_25::croak("popn() takes a positive integer or zero, not '$times'")
      66        
106             unless $times->is_integer && ($times->is_positive or $times == 0);
107              
108             # splice() will choke if you walk off the array, so rein it in
109 4 100       15 $times = scalar(@$self) if ($times > scalar(@$self));
110              
111 4         15 my @result = splice(@$self, -$times, $times);
112 4 100       22 return wantarray ? @result : \@result;
113             }
114              
115 103     103   14313 method shiftn($times) {
  7     7   9487  
  7         15  
116 7 100       249 Carp::Fix::1_25::croak("shiftn() takes the number of elements to shift")
117             unless defined $times;
118 6 100 100     48 Carp::Fix::1_25::croak("shiftn() takes a positive integer or zero, not '$times'")
      66        
119             unless $times->is_integer && ($times->is_positive or $times == 0);
120              
121             # splice() will choke if you walk off the array, so rein it in
122 4 100       17 $times = scalar(@$self) if ($times > scalar(@$self));
123              
124 4         19 my @result = splice(@$self, 0, $times);
125 4 100       21 return wantarray ? @result : \@result;
126             }
127              
128             sub all {
129 2     2 0 3842 require List::MoreUtils;
130 2         3775 return &List::MoreUtils::all($_[1], @{$_[0]});
  2         53  
131             }
132              
133             sub any {
134 2     2 0 2513 require List::MoreUtils;
135 2         1759 return &List::MoreUtils::any($_[1], @{$_[0]});
  2         338  
136             }
137              
138             sub none {
139 2     2 0 1455 require List::MoreUtils;
140 2         1297 return &List::MoreUtils::none($_[1], @{$_[0]});
  2         14  
141             }
142              
143             sub true {
144 2     2 0 2374 require List::MoreUtils;
145 2         1340 return &List::MoreUtils::true($_[1], @{$_[0]});
  2         16  
146             }
147              
148             sub false {
149 2     2 0 2021 require List::MoreUtils;
150 2         1165 return &List::MoreUtils::false($_[1], @{$_[0]});
  2         13  
151             }
152              
153             sub uniq {
154 4     4 0 2884 require List::MoreUtils;
155 4         11812 my @uniq = List::MoreUtils::uniq(@{$_[0]});
  4         78  
156 4 100       117 return wantarray ? @uniq : \@uniq;
157             }
158              
159             sub minmax {
160 3     3 0 1099 require List::MoreUtils;
161 3         2102 my @minmax = List::MoreUtils::minmax(@{$_[0]});
  3         29  
162 3 100       30 return wantarray ? @minmax : \@minmax;
163             }
164              
165             sub mesh {
166 3     3 0 1127 require List::MoreUtils;
167 3         1573 my @mesh = &List::MoreUtils::zip(@_);
168 3 100       31 return wantarray ? @mesh : \@mesh;
169             }
170              
171             # Compare differences between two arrays.
172             my $diff_two_deeply = func($c, $d) {
173             my $diff = [];
174              
175             # For each element of $c, try to find if it is equal to any of the
176             # elements of $d. If not, it's unique, and has to be pushed into
177             # $diff.
178              
179             require perl5i::2::equal;
180             require List::MoreUtils;
181             foreach my $item (@$c) {
182             unless (
183             List::MoreUtils::any( sub { perl5i::2::equal::are_equal( $item, $_ ) }, @$d )
184             )
185             {
186             push @$diff, $item;
187             }
188             }
189              
190             return $diff;
191             };
192              
193             my $diff_two_simply = func($c, $d) {
194 103     103   13775 no warnings 'uninitialized';
  103         216  
  103         16248  
195             my %seen = map { $_ => 1 } @$d;
196              
197             my @diff = grep { not $seen{$_} } @$c;
198              
199             return \@diff;
200             };
201              
202 103     103   25132 method diff(@rest) {
  42     42   5183  
  42         84  
203 42 100       120 unless (@rest) {
204 3 50       24 return wantarray ? @$self : $self;
205             }
206              
207 39         1372 require List::MoreUtils;
208              
209 39     108   1806 my $has_refs = List::MoreUtils::any(sub { ref $_ }, @$self);
  108         170  
210              
211 39 100       168 my $diff_two = $has_refs ? $diff_two_deeply : $diff_two_simply;
212              
213             # XXX If I use carp here, the exception is "bizarre copy of ARRAY in
214             # ssasign ... "
215 39 100       59 die "Arguments must be array references" if grep { ref $_ ne 'ARRAY' } @rest;
  42         208  
216              
217 35         65 foreach my $array (@rest) {
218 37         73 $self = $diff_two->($self, $array);
219             }
220              
221 35 100       271 return wantarray ? @$self : $self;
222             }
223              
224              
225             my $intersect_two_simply = func($c, $d) {
226 103     103   13769 no warnings 'uninitialized';
  103         224  
  103         13957  
227             my %seen = map { $_ => 1 } @$d;
228              
229             my @intersect = grep { $seen{$_} } @$c;
230              
231             return \@intersect;
232             };
233              
234             # Compare differences between two arrays.
235             my $intersect_two_deeply = func($c, $d) {
236             require perl5i::2::equal;
237              
238             my $intersect = [];
239              
240             # For each element of $c, try to find if it is equal to any of the
241             # elements of $d. If it is, it's shared, and has to be pushed into
242             # $intersect.
243              
244             require List::MoreUtils;
245             foreach my $item (@$c) {
246             if (
247             List::MoreUtils::any( sub { perl5i::2::equal::are_equal( $item, $_ ) }, @$d )
248             )
249             {
250             push @$intersect, $item;
251             }
252             }
253              
254             return $intersect;
255             };
256              
257 103     103   20118 method intersect(@rest) {
  37     37   2385  
  37         83  
258 37 100       108 unless (@rest) {
259 1 50       10 return wantarray ? @$self : $self;
260             }
261              
262 36         2351 require List::MoreUtils;
263 36     193   3751 my $has_refs = List::MoreUtils::any(sub { ref $_ }, @$self);
  193         223  
264              
265 36 100       151 my $intersect_two = $has_refs ? $intersect_two_deeply : $intersect_two_simply;
266              
267             # XXX If I use carp here, the exception is "bizarre copy of ARRAY in
268             # ssasign ... "
269 36 100       138 die "Arguments must be array references" if grep { ref $_ ne 'ARRAY' } @rest;
  39         203  
270              
271 32         58 foreach my $array (@rest) {
272 34         83 $self = $intersect_two->($self, $array);
273             }
274              
275 32 100       257 return wantarray ? @$self : $self;
276             }
277              
278 103     103   17563 method ltrim($charset) {
  4     4   35  
  4         9  
279 4         9 my @result = CORE::map { $_->ltrim($charset) } @$self;
  12         64  
280              
281 4 100       44 return wantarray ? @result : \@result;
282             }
283              
284 103     103   13539 method rtrim($charset) {
  4     4   8  
  4         9  
285 4         8 my @result = CORE::map { $_->rtrim($charset) } @$self;
  12         59  
286              
287 4 100       34 return wantarray ? @result : \@result;
288             }
289              
290 103     103   15144 method trim($charset) {
  5     5   11  
  5         9  
291 5         11 my @result = CORE::map { $_->trim($charset) } @$self;
  12         58  
292              
293 5 100       42 return wantarray ? @result : \@result;
294             }
295              
296              
297             1;