File Coverage

blib/lib/perl5i/2/ARRAY.pm
Criterion Covered Total %
statement 138 174 79.3
branch 45 72 62.5
condition 15 18 83.3
subroutine 46 48 95.8
pod 0 8 0.0
total 244 320 76.2


line stmt bran cond sub pod time code
1             # vi: set ts=4 sw=4 ht=4 et :
2             package perl5i::2::ARRAY;
3 101     101   2300 use 5.010;
  101         235  
  101         3955  
4              
5 101     101   406 use strict;
  101         116  
  101         3451  
6 101     101   386 use warnings;
  101         109  
  101         3839  
7 101     101   61553 no if $] >= 5.018000, warnings => 'experimental::smartmatch';
  101         846  
  101         501  
8              
9             # Don't accidentally turn carp/croak into methods.
10             require Carp::Fix::1_25;
11              
12 101     101   54620 use perl5i::2::Signatures;
  101         304  
  101         632  
13 101     101   15609 use perl5i::2::autobox;
  101         160  
  101         916  
14              
15             # A foreach which honors the number of parameters in the signature
16 101     101   13475 method foreach($code) {
  5     5   692  
  5         8  
17 5         7 my $n = 1;
18 5 100       29 if( my $sig = $code->signature ) {
19 3         18 $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         7 my $idx = 0;
24 5         7 while ( $idx <= $#{$self} ) {
  17         30  
25 12         19 $code->(@{$self}[$idx..($idx+$n-1)]);
  12         26  
26 12         33 $idx += $n;
27             }
28              
29 5         9 return;
30             }
31              
32 101     101   10629 method first($filter) {
  14     14   6166  
  14         28  
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       42 if ( ref $filter eq 'Regexp' ) {
36 1     2   10 return List::Util::first( sub { $_ ~~ $filter }, @$self );
  2         23  
37             }
38              
39 13     37   69 return List::Util::first( sub { $filter->() }, @$self );
  37         117  
40              
41             }
42              
43 101     101   10494 method map( $code ) {
  5     5   30  
  5         8  
44 5         8 my @result = CORE::map { $code->($_) } @$self;
  25         57  
45              
46 5 100       46 return wantarray ? @result : \@result;
47             }
48              
49 101     101   10258 method as_hash{
  2     2   681  
50 2         5 my %result = CORE::map { $_ => 1 } @$self;
  7         14  
51 2 100       12 return wantarray ? %result : \%result;
52             }
53              
54              
55 101     101   10230 method pick ( $num ){
  11     11   9688  
  11         20  
56 11 100       260 Carp::Fix::1_25::croak("pick() takes the number of elements to pick")
57             unless defined $num;
58 10 100 100     75 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 8 100       30 if($num >= @$self){
62 3         16 my @result = List::Util::shuffle(@$self);
63 3 50       20 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 5         7 my $num_left = @$self;
71 5         7 my @result;
72 5         8 my $i=0;
73 5         17 while($num > 0){
74 28         83 my $rand = int(rand($num_left));
75 28 100       55 if($rand < $num){
76 11         20 push(@result, $self->[$i]);
77 11         12 $num--;
78             }
79 28         29 $num_left--;
80 28         51 $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 5         46 @result = @result->shuffle;
86              
87 5 50       510 return wantarray ? @result : \@result;
88             }
89              
90              
91 101     101   10024 method pick_one() {
  3     3   1466  
92 3         16 return @$self[int rand @$self];
93             }
94              
95              
96 101     101   9984 method grep($filter) {
  14     14   5507  
  14         17  
97 14         26 my @result = CORE::grep { $_ ~~ $filter } @$self;
  46         129  
98              
99 14 100       84 return wantarray ? @result : \@result;
100             }
101              
102 101     101   9919 method popn($times) {
  7     7   4217  
  7         10  
103 7 100       169 Carp::Fix::1_25::croak("popn() takes the number of elements to pop")
104             unless defined $times;
105 6 100 100     33 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       10 $times = scalar(@$self) if ($times > scalar(@$self));
110              
111 4         11 my @result = splice(@$self, -$times, $times);
112 4 100       13 return wantarray ? @result : \@result;
113             }
114              
115 101     101   9783 method shiftn($times) {
  7     7   4160  
  7         7  
116 7 100       168 Carp::Fix::1_25::croak("shiftn() takes the number of elements to shift")
117             unless defined $times;
118 6 100 100     28 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       12 $times = scalar(@$self) if ($times > scalar(@$self));
123              
124 4         9 my @result = splice(@$self, 0, $times);
125 4 100       14 return wantarray ? @result : \@result;
126             }
127              
128             sub all {
129 1     1 0 183 require List::MoreUtils;
130 0         0 return &List::MoreUtils::all($_[1], @{$_[0]});
  0         0  
131             }
132              
133             sub any {
134 1     1 0 214 require List::MoreUtils;
135 0         0 return &List::MoreUtils::any($_[1], @{$_[0]});
  0         0  
136             }
137              
138             sub none {
139 1     1 0 207 require List::MoreUtils;
140 0         0 return &List::MoreUtils::none($_[1], @{$_[0]});
  0         0  
141             }
142              
143             sub true {
144 1     1 0 200 require List::MoreUtils;
145 0         0 return &List::MoreUtils::true($_[1], @{$_[0]});
  0         0  
146             }
147              
148             sub false {
149 1     1 0 196 require List::MoreUtils;
150 0         0 return &List::MoreUtils::false($_[1], @{$_[0]});
  0         0  
151             }
152              
153             sub uniq {
154 2     2 0 951 require List::MoreUtils;
155 0         0 my @uniq = List::MoreUtils::uniq(@{$_[0]});
  0         0  
156 0 0       0 return wantarray ? @uniq : \@uniq;
157             }
158              
159             sub minmax {
160 1     1 0 188 require List::MoreUtils;
161 0         0 my @minmax = List::MoreUtils::minmax(@{$_[0]});
  0         0  
162 0 0       0 return wantarray ? @minmax : \@minmax;
163             }
164              
165             sub mesh {
166 1     1 0 194 require List::MoreUtils;
167 0         0 my @mesh = &List::MoreUtils::zip(@_);
168 0 0       0 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 101     101   10412 no warnings 'uninitialized';
  101         158  
  101         10797  
195             my %seen = map { $_ => 1 } @$d;
196              
197             my @diff = grep { not $seen{$_} } @$c;
198              
199             return \@diff;
200             };
201              
202 101     101   10057 method diff(@rest) {
  1     1   30  
  1         3  
203 1 50       3 unless (@rest) {
204 0 0       0 return wantarray ? @$self : $self;
205             }
206              
207 1         159 require List::MoreUtils;
208              
209 0     0   0 my $has_refs = List::MoreUtils::any(sub { ref $_ }, @$self);
  0         0  
210              
211 0 0       0 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 0 0       0 die "Arguments must be array references" if grep { ref $_ ne 'ARRAY' } @rest;
  0         0  
216              
217 0         0 foreach my $array (@rest) {
218 0         0 $self = $diff_two->($self, $array);
219             }
220              
221 0 0       0 return wantarray ? @$self : $self;
222             }
223              
224              
225             my $intersect_two_simply = func($c, $d) {
226 101     101   10211 no warnings 'uninitialized';
  101         148  
  101         9640  
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 101     101   10528 method intersect(@rest) {
  2     2   47  
  2         5  
258 2 50       7 unless (@rest) {
259 0 0       0 return wantarray ? @$self : $self;
260             }
261              
262 2         367 require List::MoreUtils;
263 0     0   0 my $has_refs = List::MoreUtils::any(sub { ref $_ }, @$self);
  0         0  
264              
265 0 0       0 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 0 0       0 die "Arguments must be array references" if grep { ref $_ ne 'ARRAY' } @rest;
  0         0  
270              
271 0         0 foreach my $array (@rest) {
272 0         0 $self = $intersect_two->($self, $array);
273             }
274              
275 0 0       0 return wantarray ? @$self : $self;
276             }
277              
278 101     101   10125 method ltrim($charset) {
  4     4   27  
  4         5  
279 4         7 my @result = CORE::map { $_->ltrim($charset) } @$self;
  12         47  
280              
281 4 100       32 return wantarray ? @result : \@result;
282             }
283              
284 101     101   9714 method rtrim($charset) {
  4     4   7  
  4         6  
285 4         5 my @result = CORE::map { $_->rtrim($charset) } @$self;
  12         41  
286              
287 4 100       28 return wantarray ? @result : \@result;
288             }
289              
290 101     101   9794 method trim($charset) {
  5     5   8  
  5         6  
291 5         8 my @result = CORE::map { $_->trim($charset) } @$self;
  12         39  
292              
293 5 100       35 return wantarray ? @result : \@result;
294             }
295              
296              
297             1;