File Coverage

blib/lib/List/SomeUtils/PP.pm
Criterion Covered Total %
statement 259 272 95.2
branch 108 116 93.1
condition 35 42 83.3
subroutine 48 50 96.0
pod 0 42 0.0
total 450 522 86.2


line stmt bran cond sub pod time code
1             package List::SomeUtils::PP;
2              
3 4     4   1780 use 5.006;
  4         23  
4 4     4   14 use strict;
  4         4  
  4         59  
5 4     4   11 use warnings;
  4         4  
  4         4630  
6              
7             our $VERSION = '0.53';
8              
9             sub any (&@)
10             {
11 13     13 0 5330 my $f = shift;
12 13         29 foreach (@_)
13             {
14 40005 100       87884 return 1 if $f->();
15             }
16 2         10 return 0;
17             }
18              
19             sub all (&@)
20             {
21 9     9 0 3654 my $f = shift;
22 9         24 foreach (@_)
23             {
24 25005 100       55743 return 0 unless $f->();
25             }
26 3         27 return 1;
27             }
28              
29             sub none (&@)
30             {
31 9     9 0 3868 my $f = shift;
32 9         20 foreach (@_)
33             {
34 40002 100       87891 return 0 if $f->();
35             }
36 3         19 return 1;
37             }
38              
39             sub notall (&@)
40             {
41 9     9 0 3459 my $f = shift;
42 9         22 foreach (@_)
43             {
44 20006 100       44944 return 1 unless $f->();
45             }
46 2         10 return 0;
47             }
48              
49             sub one (&@)
50             {
51 15     15 0 85414 my $f = shift;
52 15         12041 my $found = 0;
53 15         11938 foreach (@_)
54             {
55 2667 100 100     3626981 $f->() and $found++ and return 0;
56             }
57 4         18 $found;
58             }
59              
60             sub any_u (&@)
61             {
62 13     13 0 31718 my $f = shift;
63 13 100       51 return if !@_;
64 12   100     52 $f->() and return 1 foreach (@_);
65 1         17235 return 0;
66             }
67              
68             sub all_u (&@)
69             {
70 9     9 0 3971 my $f = shift;
71 9 100       31 return if !@_;
72 8   100     37 $f->() or return 0 foreach (@_);
73 2         33764 return 1;
74             }
75              
76             sub none_u (&@)
77             {
78 9     9 0 28946 my $f = shift;
79 9 100       28 return if !@_;
80 8   100     40 $f->() and return 0 foreach (@_);
81 2         33018 return 1;
82             }
83              
84             sub notall_u (&@)
85             {
86 9     9 0 3933 my $f = shift;
87 9 100       31 return if !@_;
88 8   100     38 $f->() or return 1 foreach (@_);
89 1         17021 return 0;
90             }
91              
92             sub one_u (&@)
93             {
94 16     16 0 95497 my $f = shift;
95 16 100       14589 return if !@_;
96 15         14275 my $found = 0;
97 15         14196 foreach (@_)
98             {
99 2667 100 100     4098125 $f->() and $found++ and return 0;
100             }
101 4         24 $found;
102             }
103              
104             sub true (&@)
105             {
106 10     10 0 4979 my $f = shift;
107 10         16 my $count = 0;
108 10   66     45 $f->() and ++$count foreach (@_);
109 9         116034 return $count;
110             }
111              
112             sub false (&@)
113             {
114 10     10 0 4777 my $f = shift;
115 10         16 my $count = 0;
116 10   66     45 $f->() or ++$count foreach (@_);
117 9         118589 return $count;
118             }
119              
120             sub firstidx (&@)
121             {
122 27     27 0 10642 my $f = shift;
123 27         6904 foreach my $i ( 0 .. $#_ )
124             {
125 50048         123564 local *_ = \$_[$i];
126 50048 100       67569 return $i if $f->();
127             }
128 5         41 return -1;
129             }
130              
131             sub firstval (&@)
132             {
133 8     8 0 6231 my $test = shift;
134 8         16 foreach (@_)
135             {
136 21 100       63 return $_ if $test->();
137             }
138 3         13 return undef;
139             }
140              
141             sub firstres (&@)
142             {
143 7     7 0 5667 my $test = shift;
144 7         17 foreach (@_)
145             {
146 21         29 my $testval = $test->();
147 20 100       59 $testval and return $testval;
148             }
149 2         3 return undef;
150             }
151              
152             sub onlyidx (&@)
153             {
154 17     17 0 2937 my $f = shift;
155 17         19 my $found;
156 17         42 foreach my $i ( 0 .. $#_ )
157             {
158 3521         7944 local *_ = \$_[$i];
159 3521 100       3502 $f->() or next;
160 22 100       87 defined $found and return -1;
161 14         11 $found = $i;
162             }
163 8 100       49 return defined $found ? $found : -1;
164             }
165              
166             sub onlyval (&@)
167             {
168 17     17 0 2371 my $test = shift;
169 17         14 my $result = undef;
170 17         12 my $found = 0;
171 17         60 foreach (@_)
172             {
173 3521 100       7753 $test->() or next;
174 22         62 $result = $_;
175 22 100       51 $found++ and return undef;
176             }
177 8         34 return $result;
178             }
179              
180             sub onlyres (&@)
181             {
182 15     15 0 3009 my $test = shift;
183 15         19 my $result = undef;
184 15         20 my $found = 0;
185 15         32 foreach (@_)
186             {
187 2921 100       10927 my $rv = $test->() or next;
188 20         75 $result = $rv;
189 20 100       72 $found++ and return undef;
190             }
191 6 100       44 return $found ? $result : undef;
192             }
193              
194             sub lastidx (&@)
195             {
196 13     13 0 4394 my $f = shift;
197 13         918 foreach my $i ( reverse 0 .. $#_ )
198             {
199 20009         41745 local *_ = \$_[$i];
200 20009 100       19135 return $i if $f->();
201             }
202 4         368 return -1;
203             }
204              
205             sub lastval (&@)
206             {
207 8     8 0 5703 my $test = shift;
208 8         9 my $ix;
209 8         28 for ( $ix = $#_; $ix >= 0; $ix-- )
210             {
211 13         15 local *_ = \$_[$ix];
212 13         26 my $testval = $test->();
213              
214             # Simulate $_ as alias
215 12         29 $_[$ix] = $_;
216 12 100       32 return $_ if $testval;
217             }
218 3         6 return undef;
219             }
220              
221             sub lastres (&@)
222             {
223 7     7 0 5470 my $test = shift;
224 7         8 my $ix;
225 7         24 for ( $ix = $#_; $ix >= 0; $ix-- )
226             {
227 13         18 local *_ = \$_[$ix];
228 13         22 my $testval = $test->();
229              
230             # Simulate $_ as alias
231 12         28 $_[$ix] = $_;
232 12 100       49 return $testval if $testval;
233             }
234 2         3 return undef;
235             }
236              
237             sub insert_after (&$\@)
238             {
239 9     9 0 7513 my ( $f, $val, $list ) = @_;
240 9         30 my $c = &firstidx( $f, @$list );
241 6 100 50     33 @$list = ( @{$list}[ 0 .. $c ], $val, @{$list}[ $c + 1 .. $#$list ], ) and return 1 if $c != -1;
  5         13  
  5         52  
242 1         2 return 0;
243             }
244              
245             sub insert_after_string ($$\@)
246             {
247 8     8 0 97699 my ( $string, $val, $list ) = @_;
248 8 100   22   7022 my $c = firstidx { defined $_ and $string eq $_ } @$list;
  22         46939  
249 7 50 50     6551 @$list = ( @{$list}[ 0 .. $c ], $val, @{$list}[ $c + 1 .. $#$list ], ) and return 1 if $c != -1;
  7         12877  
  7         33041  
250 0         0 return 0;
251             }
252              
253             sub apply (&@)
254             {
255 9     9 0 11099 my $action = shift;
256 9         58 &$action foreach my @values = @_;
257 8 100       134 wantarray ? @values : $values[-1];
258             }
259              
260             sub after (&@)
261             {
262 9     9 0 92023 my $test = shift;
263 9         6473 my $started;
264             my $lag;
265             grep $started ||= do
266 9   100     6665 {
267 25         19806 my $x = $lag;
268 25         19857 $lag = $test->();
269 24         99347 $x;
270             }, @_;
271             }
272              
273             sub after_incl (&@)
274             {
275 8     8 0 123415 my $test = shift;
276 8         5930 my $started;
277 8   100     6013 grep $started ||= $test->(), @_;
278             }
279              
280             sub before (&@)
281             {
282 8     8 0 161366 my $test = shift;
283 8         8373 my $more = 1;
284 8   100     8487 grep $more &&= !$test->(), @_;
285             }
286              
287             sub before_incl (&@)
288             {
289 8     8 0 98962 my $test = shift;
290 8         7249 my $more = 1;
291 8         7425 my $lag = 1;
292             grep $more &&= do
293 8   100     7484 {
294 24         22173 my $x = $lag;
295 24         22123 $lag = !$test->();
296 23         110904 $x;
297             }, @_;
298             }
299              
300             sub indexes (&@)
301             {
302 20     20 0 16051 my $test = shift;
303             grep {
304 20         47 local *_ = \$_[$_];
  102         366  
305 102         147 $test->()
306             } 0 .. $#_;
307             }
308              
309             sub pairwise (&\@\@)
310             {
311 12     12 0 12432 my $op = shift;
312              
313             # Symbols for caller's input arrays
314 4     4   19 use vars qw{ @A @B };
  4         4  
  4         276  
315 12         30 local ( *A, *B ) = @_;
316              
317             # Localise $a, $b
318             my ( $caller_a, $caller_b ) = do
319 12         11 {
320 12         23 my $pkg = caller();
321 4     4   15 no strict 'refs';
  4         4  
  4         4103  
322 12         7 \*{ $pkg . '::a' }, \*{ $pkg . '::b' };
  12         38  
  12         26  
323             };
324              
325             # Loop iteration limit
326 12 50       31 my $limit = $#A > $#B ? $#A : $#B;
327              
328             # This map expression is also the return value
329 12         28 local ( *$caller_a, *$caller_b );
330             map {
331             # Assign to $a, $b as refs to caller's array elements
332 12         31 ( *$caller_a, *$caller_b ) = \( $A[$_], $B[$_] );
  509         3038  
333              
334             # Perform the transformation
335 509         587 $op->();
336             } 0 .. $limit;
337             }
338              
339             sub each_array (\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
340             {
341 8     8 0 9684 return each_arrayref(@_);
342             }
343              
344             sub each_arrayref
345             {
346 14     14 0 10317 my @list = @_; # The list of references to the arrays
347 14         15 my $index = 0; # Which one the caller will get next
348 14         9 my $max = 0; # Number of elements in longest array
349              
350             # Get the length of the longest input array
351 14         25 foreach (@list)
352             {
353 22 100       46 unless ( ref $_ eq 'ARRAY' )
354             {
355 2         10 require Carp;
356 2         211 Carp::croak("each_arrayref: argument is not an array reference\n");
357             }
358 20 100       40 $max = @$_ if @$_ > $max;
359             }
360              
361             # Return the iterator as a closure wrt the above variables.
362             return sub {
363 100 100   100   299 if (@_)
364             {
365 10         8 my $method = shift;
366 10 50       16 unless ( $method eq 'index' )
367             {
368 0         0 require Carp;
369 0         0 Carp::croak("each_array: unknown argument '$method' passed to iterator.");
370             }
371              
372             # Return current (last fetched) index
373 10 50 33     33 return undef if $index == 0 || $index > $max;
374 10         23 return $index - 1;
375             }
376              
377             # No more elements to return
378 90 100       109 return if $index >= $max;
379 78         53 my $i = $index++;
380              
381             # Return ith elements
382 78         135 return map $_->[$i], @list;
383             }
384 12         51 }
385              
386             sub natatime ($@)
387             {
388 4     4 0 8369 my $n = shift;
389 4         34 my @list = @_;
390             return sub {
391 1009     1009   2000 return splice @list, 0, $n;
392             }
393 4         19 }
394              
395             sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
396             {
397 12     12 0 15191 my $max = -1;
398 12   66     82 $max < $#$_ && ( $max = $#$_ ) foreach @_;
399             map {
400 10         23 my $ix = $_;
  50         31  
401 50         101 map $_->[$ix], @_;
402             } 0 .. $max;
403             }
404              
405             sub uniq (@)
406             {
407 19     19 0 12821 my %seen = ();
408 19         22 my $k;
409             my $seen_undef;
410 19 100       25 grep { defined $_ ? not $seen{ $k = $_ }++ : not $seen_undef++ } @_;
  4683         7009  
411             }
412              
413             sub singleton (@)
414             {
415 19     19 0 66477 my %seen = ();
416 19         23 my $k;
417             my $seen_undef;
418 25535 100       36102 grep { 1 == ( defined $_ ? $seen{ $k = $_ } : $seen_undef ) }
419 19 100       90 grep { defined $_ ? not $seen{ $k = $_ }++ : not $seen_undef++ } @_;
  42305         68916  
420             }
421              
422             sub minmax (@)
423             {
424 31 50   31 0 15177 return unless @_;
425 31         31 my $min = my $max = $_[0];
426              
427 31         56 for ( my $i = 1; $i < @_; $i += 2 )
428             {
429 10047 100       9407 if ( $_[ $i - 1 ] <= $_[$i] )
430             {
431 28 100       44 $min = $_[ $i - 1 ] if $min > $_[ $i - 1 ];
432 28 100       54 $max = $_[$i] if $max < $_[$i];
433             }
434             else
435             {
436 10019 100       11189 $min = $_[$i] if $min > $_[$i];
437 10019 100       17949 $max = $_[ $i - 1 ] if $max < $_[ $i - 1 ];
438             }
439             }
440              
441 31 100       57 if ( @_ & 1 )
442             {
443 25         23 my $i = $#_;
444 25 100       49 if ( $_[ $i - 1 ] <= $_[$i] )
445             {
446 22 50       37 $min = $_[ $i - 1 ] if $min > $_[ $i - 1 ];
447 22 100       33 $max = $_[$i] if $max < $_[$i];
448             }
449             else
450             {
451 3 50       12 $min = $_[$i] if $min > $_[$i];
452 3 50       11 $max = $_[ $i - 1 ] if $max < $_[ $i - 1 ];
453             }
454             }
455              
456 31         75 return ( $min, $max );
457             }
458              
459             sub part (&@)
460             {
461 11     11 0 24728 my ( $code, @list ) = @_;
462 11         15 my @parts;
463 11         44 push @{ $parts[ $code->($_) ] }, $_ foreach @list;
  99         420  
464 10         1002 return @parts;
465             }
466              
467             sub bsearch(&@)
468             {
469 2029     2029 0 526980 my $code = shift;
470              
471 2029         2160 my $rc;
472 2029         1635 my $i = 0;
473 2029         1997 my $j = @_;
474             do
475 2029         1569 {
476 18242         16052 my $k = int( ( $i + $j ) / 2 );
477              
478 18242 100       21100 $k >= @_ and return;
479              
480 18231         15626 local *_ = \$_[$k];
481 18231         20382 $rc = $code->();
482              
483 18228 100       39639 $rc == 0
    100          
484             and return wantarray ? $_ : 1;
485              
486 16224 100       15575 if ( $rc < 0 )
487             {
488 8205         11919 $i = $k + 1;
489             }
490             else
491             {
492 8019         11890 $j = $k - 1;
493             }
494             } until $i > $j;
495              
496 11         18 return;
497             }
498              
499             sub bsearchidx(&@)
500             {
501 1029     1029 0 308808 my $code = shift;
502              
503 1029         757 my $rc;
504 1029         787 my $i = 0;
505 1029         783 my $j = @_;
506             do
507 1029         793 {
508 9255         7919 my $k = int( ( $i + $j ) / 2 );
509              
510 9255 100       10482 $k >= @_ and return -1;
511              
512 9244         7749 local *_ = \$_[$k];
513 9244         9989 $rc = $code->();
514              
515 9241 100       19846 $rc == 0 and return $k;
516              
517 8237 100       7965 if ( $rc < 0 )
518             {
519 4169         6006 $i = $k + 1;
520             }
521             else
522             {
523 4068         5685 $j = $k - 1;
524             }
525             } until $i > $j;
526              
527 11         13 return -1;
528             }
529              
530             sub sort_by(&@)
531             {
532 0     0 0   my ( $code, @list ) = @_;
533 0           return map { $_->[0] }
534 0           sort { $a->[1] cmp $b->[1] }
535 0           map { [ $_, scalar( $code->() ) ] } @list;
  0            
536             }
537              
538             sub nsort_by(&@)
539             {
540 0     0 0   my ( $code, @list ) = @_;
541 0           return map { $_->[0] }
542 0           sort { $a->[1] <=> $b->[1] }
543 0           map { [ $_, scalar( $code->() ) ] } @list;
  0            
544             }
545              
546             1;
547              
548             # ABSTRACT: Pure Perl implementation for List::SomeUtils
549              
550             __END__