File Coverage

blib/lib/List/SomeUtils/PP.pm
Criterion Covered Total %
statement 267 280 95.3
branch 109 116 93.9
condition 35 42 83.3
subroutine 50 52 96.1
pod 0 43 0.0
total 461 533 86.4


line stmt bran cond sub pod time code
1             package List::SomeUtils::PP;
2              
3 4     4   4360 use 5.006;
  4         53  
4 4     4   26 use strict;
  4         10  
  4         126  
5 4     4   26 use warnings;
  4         10  
  4         166  
6              
7 4     4   29 use List::Util qw( max );
  4         9  
  4         8835  
8              
9             our $VERSION = '0.56';
10              
11             sub any (&@)
12             {
13 13     13 0 7769 my $f = shift;
14 13         39 foreach (@_)
15             {
16 40005 100       153676 return 1 if $f->();
17             }
18 2         12 return 0;
19             }
20              
21             sub all (&@)
22             {
23 9     9 0 6566 my $f = shift;
24 9         23 foreach (@_)
25             {
26 25005 100       98239 return 0 unless $f->();
27             }
28 3         56 return 1;
29             }
30              
31             sub none (&@)
32             {
33 9     9 0 6677 my $f = shift;
34 9         32 foreach (@_)
35             {
36 40002 100       188084 return 0 if $f->();
37             }
38 3         37 return 1;
39             }
40              
41             sub notall (&@)
42             {
43 9     9 0 8089 my $f = shift;
44 9         27 foreach (@_)
45             {
46 20006 100       76527 return 1 unless $f->();
47             }
48 2         15 return 0;
49             }
50              
51             sub one (&@)
52             {
53 15     15 0 107201 my $f = shift;
54 15         12597 my $found = 0;
55 15         12538 foreach (@_)
56             {
57 2667 100 100     4730210 $f->() and $found++ and return 0;
58             }
59 4         28 $found;
60             }
61              
62             sub any_u (&@)
63             {
64 13     13 0 60257 my $f = shift;
65 13 100       67 return if !@_;
66 12   100     88 $f->() and return 1 foreach (@_);
67 1         28109 return 0;
68             }
69              
70             sub all_u (&@)
71             {
72 9     9 0 9860 my $f = shift;
73 9 100       49 return if !@_;
74 8   100     59 $f->() or return 0 foreach (@_);
75 2         58480 return 1;
76             }
77              
78             sub none_u (&@)
79             {
80 9     9 0 53490 my $f = shift;
81 9 100       58 return if !@_;
82 8   100     66 $f->() and return 0 foreach (@_);
83 2         64493 return 1;
84             }
85              
86             sub notall_u (&@)
87             {
88 9     9 0 10011 my $f = shift;
89 9 100       60 return if !@_;
90 8   100     76 $f->() or return 1 foreach (@_);
91 1         31982 return 0;
92             }
93              
94             sub one_u (&@)
95             {
96 16     16 0 141720 my $f = shift;
97 16 100       18651 return if !@_;
98 15         22752 my $found = 0;
99 15         24214 foreach (@_)
100             {
101 2667 100 100     5857272 $f->() and $found++ and return 0;
102             }
103 4         44 $found;
104             }
105              
106             sub true (&@)
107             {
108 10     10 0 9158 my $f = shift;
109 10         22 my $count = 0;
110 10   66     50 $f->() and ++$count foreach (@_);
111 9         156932 return $count;
112             }
113              
114             sub false (&@)
115             {
116 10     10 0 9323 my $f = shift;
117 10         24 my $count = 0;
118 10   66     52 $f->() or ++$count foreach (@_);
119 9         158209 return $count;
120             }
121              
122             sub firstidx (&@)
123             {
124 27     27 0 13245 my $f = shift;
125 27         5938 foreach my $i ( 0 .. $#_ )
126             {
127 50048         203604 local *_ = \$_[$i];
128 50048 100       101920 return $i if $f->();
129             }
130 5         38 return -1;
131             }
132              
133             sub firstval (&@)
134             {
135 8     8 0 12841 my $test = shift;
136 8         19 foreach (@_)
137             {
138 21 100       90 return $_ if $test->();
139             }
140 3         18 return undef;
141             }
142              
143             sub firstres (&@)
144             {
145 7     7 0 10639 my $test = shift;
146 7         23 foreach (@_)
147             {
148 21         57 my $testval = $test->();
149 20 100       100 $testval and return $testval;
150             }
151 2         6 return undef;
152             }
153              
154             sub onlyidx (&@)
155             {
156 17     17 0 7255 my $f = shift;
157 17         37 my $found;
158 17         65 foreach my $i ( 0 .. $#_ )
159             {
160 3521         17281 local *_ = \$_[$i];
161 3521 100       8129 $f->() or next;
162 22 100       166 defined $found and return -1;
163 14         40 $found = $i;
164             }
165 8 100       87 return defined $found ? $found : -1;
166             }
167              
168             sub onlyval (&@)
169             {
170 17     17 0 6097 my $test = shift;
171 17         24 my $result = undef;
172 17         23 my $found = 0;
173 17         33 foreach (@_)
174             {
175 3521 100       10941 $test->() or next;
176 22         74 $result = $_;
177 22 100       65 $found++ and return undef;
178             }
179 8         57 return $result;
180             }
181              
182             sub onlyres (&@)
183             {
184 15     15 0 4961 my $test = shift;
185 15         27 my $result = undef;
186 15         24 my $found = 0;
187 15         28 foreach (@_)
188             {
189 2921 100       10172 my $rv = $test->() or next;
190 20         63 $result = $rv;
191 20 100       57 $found++ and return undef;
192             }
193 6 100       40 return $found ? $result : undef;
194             }
195              
196             sub lastidx (&@)
197             {
198 13     13 0 7462 my $f = shift;
199 13         1168 foreach my $i ( reverse 0 .. $#_ )
200             {
201 20009         86431 local *_ = \$_[$i];
202 20009 100       38749 return $i if $f->();
203             }
204 4         441 return -1;
205             }
206              
207             sub lastval (&@)
208             {
209 8     8 0 12001 my $test = shift;
210 8         18 my $ix;
211 8         32 for ( $ix = $#_; $ix >= 0; $ix-- )
212             {
213 13         34 local *_ = \$_[$ix];
214 13         44 my $testval = $test->();
215              
216             # Simulate $_ as alias
217 12         51 $_[$ix] = $_;
218 12 100       46 return $_ if $testval;
219             }
220 3         9 return undef;
221             }
222              
223             sub lastres (&@)
224             {
225 7     7 0 9998 my $test = shift;
226 7         12 my $ix;
227 7         26 for ( $ix = $#_; $ix >= 0; $ix-- )
228             {
229 13         24 local *_ = \$_[$ix];
230 13         32 my $testval = $test->();
231              
232             # Simulate $_ as alias
233 12         36 $_[$ix] = $_;
234 12 100       35 return $testval if $testval;
235             }
236 2         5 return undef;
237             }
238              
239             sub insert_after (&$\@)
240             {
241 9     9 0 14418 my ( $f, $val, $list ) = @_;
242 9         46 my $c = &firstidx( $f, @$list );
243 6 100 50     48 @$list = ( @{$list}[ 0 .. $c ], $val, @{$list}[ $c + 1 .. $#$list ], ) and return 1 if $c != -1;
  5         21  
  5         37  
244 1         3 return 0;
245             }
246              
247             sub insert_after_string ($$\@)
248             {
249 8     8 0 111716 my ( $string, $val, $list ) = @_;
250 8 100   22   5814 my $c = firstidx { defined $_ and $string eq $_ } @$list;
  22         50741  
251 7 50 50     5978 @$list = ( @{$list}[ 0 .. $c ], $val, @{$list}[ $c + 1 .. $#$list ], ) and return 1 if $c != -1;
  7         12248  
  7         29933  
252 0         0 return 0;
253             }
254              
255             sub apply (&@)
256             {
257 9     9 0 15263 my $action = shift;
258 9         40 &$action foreach my @values = @_;
259 8 100       144 wantarray ? @values : $values[-1];
260             }
261              
262             sub after (&@)
263             {
264 9     9 0 110315 my $test = shift;
265 9         7789 my $started;
266             my $lag;
267             grep $started ||= do
268 9   100     6569 {
269 25         21655 my $x = $lag;
270 25         21528 $lag = $test->();
271 24         109210 $x;
272             }, @_;
273             }
274              
275             sub after_incl (&@)
276             {
277 8     8 0 174129 my $test = shift;
278 8         6288 my $started;
279 8   100     7995 grep $started ||= $test->(), @_;
280             }
281              
282             sub before (&@)
283             {
284 8     8 0 146015 my $test = shift;
285 8         6154 my $more = 1;
286 8   100     6143 grep $more &&= !$test->(), @_;
287             }
288              
289             sub before_incl (&@)
290             {
291 8     8 0 99687 my $test = shift;
292 8         7281 my $more = 1;
293 8         7903 my $lag = 1;
294             grep $more &&= do
295 8   100     7154 {
296 24         19142 my $x = $lag;
297 24         22712 $lag = !$test->();
298 23         95533 $x;
299             }, @_;
300             }
301              
302             sub indexes (&@)
303             {
304 20     20 0 18384 my $test = shift;
305             grep {
306 20         40 local *_ = \$_[$_];
  102         394  
307 102         163 $test->()
308             } 0 .. $#_;
309             }
310              
311             sub pairwise (&\@\@)
312             {
313 12     12 0 20766 my $op = shift;
314              
315             # Symbols for caller's input arrays
316 4     4   42 use vars qw{ @A @B };
  4         11  
  4         419  
317 12         43 local ( *A, *B ) = @_;
318              
319             # Localise $a, $b
320             my ( $caller_a, $caller_b ) = do
321 12         21 {
322 12         27 my $pkg = caller();
323 4     4   30 no strict 'refs';
  4         18  
  4         6403  
324 12         19 \*{ $pkg . '::a' }, \*{ $pkg . '::b' };
  12         47  
  12         42  
325             };
326              
327             # Loop iteration limit
328 12 100       43 my $limit = $#A > $#B ? $#A : $#B;
329              
330             # This map expression is also the return value
331 12         36 local ( *$caller_a, *$caller_b );
332             map {
333             # Assign to $a, $b as refs to caller's array elements
334 12         38 ( *$caller_a, *$caller_b ) = \( $A[$_], $B[$_] );
  522         2913  
335              
336             # Perform the transformation
337 522         803 $op->();
338             } 0 .. $limit;
339             }
340              
341             sub each_array (\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
342             {
343 8     8 0 14866 return each_arrayref(@_);
344             }
345              
346             sub each_arrayref
347             {
348 14     14 0 14722 my @list = @_; # The list of references to the arrays
349 14         25 my $index = 0; # Which one the caller will get next
350 14         23 my $max = 0; # Number of elements in longest array
351              
352             # Get the length of the longest input array
353 14         30 foreach (@list)
354             {
355 22 100       55 unless ( ref $_ eq 'ARRAY' )
356             {
357 2         13 require Carp;
358 2         204 Carp::croak("each_arrayref: argument is not an array reference\n");
359             }
360 20 100       50 $max = @$_ if @$_ > $max;
361             }
362              
363             # Return the iterator as a closure wrt the above variables.
364             return sub {
365 100 100   100   440 if (@_)
366             {
367 10         19 my $method = shift;
368 10 50       25 unless ( $method eq 'index' )
369             {
370 0         0 require Carp;
371 0         0 Carp::croak("each_array: unknown argument '$method' passed to iterator.");
372             }
373              
374             # Return current (last fetched) index
375 10 50 33     38 return undef if $index == 0 || $index > $max;
376 10         33 return $index - 1;
377             }
378              
379             # No more elements to return
380 90 100       152 return if $index >= $max;
381 78         98 my $i = $index++;
382              
383             # Return ith elements
384 78         224 return map $_->[$i], @list;
385             }
386 12         74 }
387              
388             sub natatime ($@)
389             {
390 4     4 0 17269 my $n = shift;
391 4         29 my @list = @_;
392             return sub {
393 1009     1009   2742 return splice @list, 0, $n;
394             }
395 4         30 }
396              
397             sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
398             {
399 12     12 0 27999 my $max = -1;
400 12   66     94 $max < $#$_ && ( $max = $#$_ ) foreach @_;
401             map {
402 10         36 my $ix = $_;
  50         85  
403 50         179 map $_->[$ix], @_;
404             } 0 .. $max;
405             }
406              
407             sub uniq (@)
408             {
409 19     19 0 27861 my %seen = ();
410 19         51 my $k;
411             my $seen_undef;
412 19 100       58 grep { defined $_ ? not $seen{ $k = $_ }++ : not $seen_undef++ } @_;
  4683         17810  
413             }
414              
415             sub singleton (@)
416             {
417 19     19 0 131485 my %seen = ();
418 19         58 my $k;
419             my $seen_undef;
420 25535 100       78929 grep { 1 == ( defined $_ ? $seen{ $k = $_ } : $seen_undef ) }
421 19 100       135 grep { defined $_ ? not $seen{ $k = $_ }++ : not $seen_undef++ } @_;
  42305         146060  
422             }
423              
424             sub minmax (@)
425             {
426 31 50   31 0 34358 return unless @_;
427 31         80 my $min = my $max = $_[0];
428              
429 31         110 for ( my $i = 1; $i < @_; $i += 2 )
430             {
431 10047 100       17877 if ( $_[ $i - 1 ] <= $_[$i] )
432             {
433 28 100       69 $min = $_[ $i - 1 ] if $min > $_[ $i - 1 ];
434 28 100       87 $max = $_[$i] if $max < $_[$i];
435             }
436             else
437             {
438 10019 100       18465 $min = $_[$i] if $min > $_[$i];
439 10019 100       23731 $max = $_[ $i - 1 ] if $max < $_[ $i - 1 ];
440             }
441             }
442              
443 31 100       96 if ( @_ & 1 )
444             {
445 25         64 my $i = $#_;
446 25 100       113 if ( $_[ $i - 1 ] <= $_[$i] )
447             {
448 22 50       86 $min = $_[ $i - 1 ] if $min > $_[ $i - 1 ];
449 22 100       82 $max = $_[$i] if $max < $_[$i];
450             }
451             else
452             {
453 3 50       14 $min = $_[$i] if $min > $_[$i];
454 3 50       18 $max = $_[ $i - 1 ] if $max < $_[ $i - 1 ];
455             }
456             }
457              
458 31         154 return ( $min, $max );
459             }
460              
461             sub part (&@)
462             {
463 11     11 0 44059 my ( $code, @list ) = @_;
464 11         30 my @parts;
465 11         38 push @{ $parts[ $code->($_) ] }, $_ foreach @list;
  99         796  
466 10         919 return @parts;
467             }
468              
469             sub bsearch(&@)
470             {
471 2029     2029 0 985225 my $code = shift;
472              
473 2029         3731 my $rc;
474 2029         3530 my $i = 0;
475 2029         3636 my $j = @_;
476             do
477 2029         3399 {
478 18240         36885 my $k = int( ( $i + $j ) / 2 );
479              
480 18240 100       37937 $k >= @_ and return;
481              
482 18229         34576 local *_ = \$_[$k];
483 18229         38110 $rc = $code->();
484              
485 18226 100       70086 $rc == 0
    100          
486             and return wantarray ? $_ : 1;
487              
488 16222 100       30676 if ( $rc < 0 )
489             {
490 8210         19336 $i = $k + 1;
491             }
492             else
493             {
494 8012         18955 $j = $k - 1;
495             }
496             } until $i > $j;
497              
498 11         23 return;
499             }
500              
501             sub bsearchidx(&@)
502             {
503 1029     1029 0 809946 my $code = shift;
504              
505 1029         2093 my $rc;
506 1029         1727 my $i = 0;
507 1029         1904 my $j = @_;
508             do
509 1029         1728 {
510 9254         18240 my $k = int( ( $i + $j ) / 2 );
511              
512 9254 100       19406 $k >= @_ and return -1;
513              
514 9243         17588 local *_ = \$_[$k];
515 9243         19728 $rc = $code->();
516              
517 9240 100       37010 $rc == 0 and return $k;
518              
519 8236 100       15904 if ( $rc < 0 )
520             {
521 4169         9570 $i = $k + 1;
522             }
523             else
524             {
525 4067         9849 $j = $k - 1;
526             }
527             } until $i > $j;
528              
529 11         23 return -1;
530             }
531              
532             sub sort_by(&@)
533             {
534 0     0 0 0 my ( $code, @list ) = @_;
535 0         0 return map { $_->[0] }
536 0         0 sort { $a->[1] cmp $b->[1] }
537 0         0 map { [ $_, scalar( $code->() ) ] } @list;
  0         0  
538             }
539              
540             sub nsort_by(&@)
541             {
542 0     0 0 0 my ( $code, @list ) = @_;
543 0         0 return map { $_->[0] }
544 0         0 sort { $a->[1] <=> $b->[1] }
545 0         0 map { [ $_, scalar( $code->() ) ] } @list;
  0         0  
546             }
547              
548             sub mode (@) {
549 20     20 0 13171 my %v;
550 20         118 $v{$_}++ for @_;
551 20         81 my $max = max( values %v );
552 20         55 return grep { $v{$_} == $max } keys %v;
  60         177  
553             }
554              
555             1;
556              
557             # ABSTRACT: Pure Perl implementation for List::SomeUtils
558              
559             __END__