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   2539 use 5.006;
  4         29  
4 4     4   19 use strict;
  4         6  
  4         68  
5 4     4   16 use warnings;
  4         8  
  4         4990  
6              
7             our $VERSION = '0.54';
8              
9             sub any (&@)
10             {
11 13     13 0 6227 my $f = shift;
12 13         45 foreach (@_)
13             {
14 40005 100       146490 return 1 if $f->();
15             }
16 2         19 return 0;
17             }
18              
19             sub all (&@)
20             {
21 9     9 0 4056 my $f = shift;
22 9         27 foreach (@_)
23             {
24 25005 100       91863 return 0 unless $f->();
25             }
26 3         24 return 1;
27             }
28              
29             sub none (&@)
30             {
31 9     9 0 3962 my $f = shift;
32 9         29 foreach (@_)
33             {
34 40002 100       143517 return 0 if $f->();
35             }
36 3         25 return 1;
37             }
38              
39             sub notall (&@)
40             {
41 9     9 0 3988 my $f = shift;
42 9         26 foreach (@_)
43             {
44 20006 100       71313 return 1 unless $f->();
45             }
46 2         14 return 0;
47             }
48              
49             sub one (&@)
50             {
51 15     15 0 97203 my $f = shift;
52 15         12345 my $found = 0;
53 15         12224 foreach (@_)
54             {
55 2667 100 100     3952391 $f->() and $found++ and return 0;
56             }
57 4         28 $found;
58             }
59              
60             sub any_u (&@)
61             {
62 13     13 0 39161 my $f = shift;
63 13 100       51 return if !@_;
64 12   100     54 $f->() and return 1 foreach (@_);
65 1         22465 return 0;
66             }
67              
68             sub all_u (&@)
69             {
70 9     9 0 3809 my $f = shift;
71 9 100       32 return if !@_;
72 8   100     43 $f->() or return 0 foreach (@_);
73 2         45050 return 1;
74             }
75              
76             sub none_u (&@)
77             {
78 9     9 0 36904 my $f = shift;
79 9 100       31 return if !@_;
80 8   100     39 $f->() and return 0 foreach (@_);
81 2         44496 return 1;
82             }
83              
84             sub notall_u (&@)
85             {
86 9     9 0 3694 my $f = shift;
87 9 100       52 return if !@_;
88 8   100     39 $f->() or return 1 foreach (@_);
89 1         22459 return 0;
90             }
91              
92             sub one_u (&@)
93             {
94 16     16 0 79045 my $f = shift;
95 16 100       11489 return if !@_;
96 15         10887 my $found = 0;
97 15         11257 foreach (@_)
98             {
99 2667 100 100     3474586 $f->() and $found++ and return 0;
100             }
101 4         30 $found;
102             }
103              
104             sub true (&@)
105             {
106 10     10 0 5311 my $f = shift;
107 10         21 my $count = 0;
108 10   66     52 $f->() and ++$count foreach (@_);
109 9         158746 return $count;
110             }
111              
112             sub false (&@)
113             {
114 10     10 0 5315 my $f = shift;
115 10         21 my $count = 0;
116 10   66     50 $f->() or ++$count foreach (@_);
117 9         165462 return $count;
118             }
119              
120             sub firstidx (&@)
121             {
122 27     27 0 9761 my $f = shift;
123 27         5537 foreach my $i ( 0 .. $#_ )
124             {
125 50048         192574 local *_ = \$_[$i];
126 50048 100       101214 return $i if $f->();
127             }
128 5         42 return -1;
129             }
130              
131             sub firstval (&@)
132             {
133 8     8 0 7175 my $test = shift;
134 8         23 foreach (@_)
135             {
136 21 100       90 return $_ if $test->();
137             }
138 3         15 return undef;
139             }
140              
141             sub firstres (&@)
142             {
143 7     7 0 7032 my $test = shift;
144 7         17 foreach (@_)
145             {
146 21         54 my $testval = $test->();
147 20 100       85 $testval and return $testval;
148             }
149 2         5 return undef;
150             }
151              
152             sub onlyidx (&@)
153             {
154 17     17 0 2887 my $f = shift;
155 17         33 my $found;
156 17         52 foreach my $i ( 0 .. $#_ )
157             {
158 3521         12782 local *_ = \$_[$i];
159 3521 100       6090 $f->() or next;
160 22 100       114 defined $found and return -1;
161 14         29 $found = $i;
162             }
163 8 100       55 return defined $found ? $found : -1;
164             }
165              
166             sub onlyval (&@)
167             {
168 17     17 0 2853 my $test = shift;
169 17         34 my $result = undef;
170 17         26 my $found = 0;
171 17         43 foreach (@_)
172             {
173 3521 100       12998 $test->() or next;
174 22         83 $result = $_;
175 22 100       68 $found++ and return undef;
176             }
177 8         51 return $result;
178             }
179              
180             sub onlyres (&@)
181             {
182 15     15 0 2741 my $test = shift;
183 15         26 my $result = undef;
184 15         25 my $found = 0;
185 15         33 foreach (@_)
186             {
187 2921 100       11567 my $rv = $test->() or next;
188 20         74 $result = $rv;
189 20 100       62 $found++ and return undef;
190             }
191 6 100       43 return $found ? $result : undef;
192             }
193              
194             sub lastidx (&@)
195             {
196 13     13 0 4097 my $f = shift;
197 13         877 foreach my $i ( reverse 0 .. $#_ )
198             {
199 20009         71272 local *_ = \$_[$i];
200 20009 100       34626 return $i if $f->();
201             }
202 4         365 return -1;
203             }
204              
205             sub lastval (&@)
206             {
207 8     8 0 6613 my $test = shift;
208 8         17 my $ix;
209 8         30 for ( $ix = $#_; $ix >= 0; $ix-- )
210             {
211 13         29 local *_ = \$_[$ix];
212 13         39 my $testval = $test->();
213              
214             # Simulate $_ as alias
215 12         40 $_[$ix] = $_;
216 12 100       41 return $_ if $testval;
217             }
218 3         10 return undef;
219             }
220              
221             sub lastres (&@)
222             {
223 7     7 0 7221 my $test = shift;
224 7         13 my $ix;
225 7         29 for ( $ix = $#_; $ix >= 0; $ix-- )
226             {
227 13         29 local *_ = \$_[$ix];
228 13         37 my $testval = $test->();
229              
230             # Simulate $_ as alias
231 12         42 $_[$ix] = $_;
232 12 100       45 return $testval if $testval;
233             }
234 2         5 return undef;
235             }
236              
237             sub insert_after (&$\@)
238             {
239 9     9 0 8056 my ( $f, $val, $list ) = @_;
240 9         37 my $c = &firstidx( $f, @$list );
241 6 100 50     36 @$list = ( @{$list}[ 0 .. $c ], $val, @{$list}[ $c + 1 .. $#$list ], ) and return 1 if $c != -1;
  5         14  
  5         25  
242 1         3 return 0;
243             }
244              
245             sub insert_after_string ($$\@)
246             {
247 8     8 0 88308 my ( $string, $val, $list ) = @_;
248 8 100   22   5797 my $c = firstidx { defined $_ and $string eq $_ } @$list;
  22         39467  
249 7 50 50     5682 @$list = ( @{$list}[ 0 .. $c ], $val, @{$list}[ $c + 1 .. $#$list ], ) and return 1 if $c != -1;
  7         10942  
  7         27921  
250 0         0 return 0;
251             }
252              
253             sub apply (&@)
254             {
255 9     9 0 14393 my $action = shift;
256 9         52 &$action foreach my @values = @_;
257 8 100       180 wantarray ? @values : $values[-1];
258             }
259              
260             sub after (&@)
261             {
262 9     9 0 96527 my $test = shift;
263 9         5545 my $started;
264             my $lag;
265             grep $started ||= do
266 9   100     5654 {
267 25         16407 my $x = $lag;
268 25         16923 $lag = $test->();
269 24         81311 $x;
270             }, @_;
271             }
272              
273             sub after_incl (&@)
274             {
275 8     8 0 114936 my $test = shift;
276 8         5248 my $started;
277 8   100     5464 grep $started ||= $test->(), @_;
278             }
279              
280             sub before (&@)
281             {
282 8     8 0 138895 my $test = shift;
283 8         5413 my $more = 1;
284 8   100     5474 grep $more &&= !$test->(), @_;
285             }
286              
287             sub before_incl (&@)
288             {
289 8     8 0 82802 my $test = shift;
290 8         5741 my $more = 1;
291 8         5739 my $lag = 1;
292             grep $more &&= do
293 8   100     6349 {
294 24         17692 my $x = $lag;
295 24         17698 $lag = !$test->();
296 23         82425 $x;
297             }, @_;
298             }
299              
300             sub indexes (&@)
301             {
302 20     20 0 21222 my $test = shift;
303             grep {
304 20         50 local *_ = \$_[$_];
  102         497  
305 102         214 $test->()
306             } 0 .. $#_;
307             }
308              
309             sub pairwise (&\@\@)
310             {
311 12     12 0 21559 my $op = shift;
312              
313             # Symbols for caller's input arrays
314 4     4   29 use vars qw{ @A @B };
  4         8  
  4         298  
315 12         42 local ( *A, *B ) = @_;
316              
317             # Localise $a, $b
318             my ( $caller_a, $caller_b ) = do
319 12         23 {
320 12         27 my $pkg = caller();
321 4     4   23 no strict 'refs';
  4         12  
  4         3616  
322 12         20 \*{ $pkg . '::a' }, \*{ $pkg . '::b' };
  12         49  
  12         38  
323             };
324              
325             # Loop iteration limit
326 12 50       40 my $limit = $#A > $#B ? $#A : $#B;
327              
328             # This map expression is also the return value
329 12         40 local ( *$caller_a, *$caller_b );
330             map {
331             # Assign to $a, $b as refs to caller's array elements
332 12         42 ( *$caller_a, *$caller_b ) = \( $A[$_], $B[$_] );
  1019         4108  
333              
334             # Perform the transformation
335 1019         1850 $op->();
336             } 0 .. $limit;
337             }
338              
339             sub each_array (\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
340             {
341 8     8 0 12502 return each_arrayref(@_);
342             }
343              
344             sub each_arrayref
345             {
346 14     14 0 14911 my @list = @_; # The list of references to the arrays
347 14         25 my $index = 0; # Which one the caller will get next
348 14         25 my $max = 0; # Number of elements in longest array
349              
350             # Get the length of the longest input array
351 14         31 foreach (@list)
352             {
353 22 100       63 unless ( ref $_ eq 'ARRAY' )
354             {
355 2         12 require Carp;
356 2         218 Carp::croak("each_arrayref: argument is not an array reference\n");
357             }
358 20 100       57 $max = @$_ if @$_ > $max;
359             }
360              
361             # Return the iterator as a closure wrt the above variables.
362             return sub {
363 100 100   100   467 if (@_)
364             {
365 10         15 my $method = shift;
366 10 50       21 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     41 return undef if $index == 0 || $index > $max;
374 10         30 return $index - 1;
375             }
376              
377             # No more elements to return
378 90 100       177 return if $index >= $max;
379 78         110 my $i = $index++;
380              
381             # Return ith elements
382 78         206 return map $_->[$i], @list;
383             }
384 12         62 }
385              
386             sub natatime ($@)
387             {
388 4     4 0 13496 my $n = shift;
389 4         56 my @list = @_;
390             return sub {
391 1009     1009   3233 return splice @list, 0, $n;
392             }
393 4         24 }
394              
395             sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
396             {
397 12     12 0 18657 my $max = -1;
398 12   66     95 $max < $#$_ && ( $max = $#$_ ) foreach @_;
399             map {
400 10         29 my $ix = $_;
  50         73  
401 50         137 map $_->[$ix], @_;
402             } 0 .. $max;
403             }
404              
405             sub uniq (@)
406             {
407 19     19 0 20120 my %seen = ();
408 19         52 my $k;
409             my $seen_undef;
410 19 100       60 grep { defined $_ ? not $seen{ $k = $_ }++ : not $seen_undef++ } @_;
  4683         16198  
411             }
412              
413             sub singleton (@)
414             {
415 19     19 0 85261 my %seen = ();
416 19         58 my $k;
417             my $seen_undef;
418 25535 100       60390 grep { 1 == ( defined $_ ? $seen{ $k = $_ } : $seen_undef ) }
419 19 100       107 grep { defined $_ ? not $seen{ $k = $_ }++ : not $seen_undef++ } @_;
  42305         114924  
420             }
421              
422             sub minmax (@)
423             {
424 31 50   31 0 15679 return unless @_;
425 31         60 my $min = my $max = $_[0];
426              
427 31         79 for ( my $i = 1; $i < @_; $i += 2 )
428             {
429 10047 100       17570 if ( $_[ $i - 1 ] <= $_[$i] )
430             {
431 28 100       72 $min = $_[ $i - 1 ] if $min > $_[ $i - 1 ];
432 28 100       81 $max = $_[$i] if $max < $_[$i];
433             }
434             else
435             {
436 10019 100       19322 $min = $_[$i] if $min > $_[$i];
437 10019 100       25711 $max = $_[ $i - 1 ] if $max < $_[ $i - 1 ];
438             }
439             }
440              
441 31 100       85 if ( @_ & 1 )
442             {
443 25         34 my $i = $#_;
444 25 100       73 if ( $_[ $i - 1 ] <= $_[$i] )
445             {
446 22 50       58 $min = $_[ $i - 1 ] if $min > $_[ $i - 1 ];
447 22 100       50 $max = $_[$i] if $max < $_[$i];
448             }
449             else
450             {
451 3 50       11 $min = $_[$i] if $min > $_[$i];
452 3 50       13 $max = $_[ $i - 1 ] if $max < $_[ $i - 1 ];
453             }
454             }
455              
456 31         102 return ( $min, $max );
457             }
458              
459             sub part (&@)
460             {
461 11     11 0 29011 my ( $code, @list ) = @_;
462 11         26 my @parts;
463 11         29 push @{ $parts[ $code->($_) ] }, $_ foreach @list;
  99         539  
464 10         820 return @parts;
465             }
466              
467             sub bsearch(&@)
468             {
469 2029     2029 0 735833 my $code = shift;
470              
471 2029         3298 my $rc;
472 2029         3184 my $i = 0;
473 2029         3441 my $j = @_;
474             do
475 2029         3220 {
476 18235         29976 my $k = int( ( $i + $j ) / 2 );
477              
478 18235 100       35966 $k >= @_ and return;
479              
480 18224         29711 local *_ = \$_[$k];
481 18224         35226 $rc = $code->();
482              
483 18221 100       64087 $rc == 0
    100          
484             and return wantarray ? $_ : 1;
485              
486 16217 100       28793 if ( $rc < 0 )
487             {
488 8207         17866 $i = $k + 1;
489             }
490             else
491             {
492 8010         17269 $j = $k - 1;
493             }
494             } until $i > $j;
495              
496 11         20 return;
497             }
498              
499             sub bsearchidx(&@)
500             {
501 1029     1029 0 505032 my $code = shift;
502              
503 1029         1701 my $rc;
504 1029         1521 my $i = 0;
505 1029         1695 my $j = @_;
506             do
507 1029         1547 {
508 9253         15370 my $k = int( ( $i + $j ) / 2 );
509              
510 9253 100       18394 $k >= @_ and return -1;
511              
512 9242         15401 local *_ = \$_[$k];
513 9242         17688 $rc = $code->();
514              
515 9239 100       32831 $rc == 0 and return $k;
516              
517 8235 100       14872 if ( $rc < 0 )
518             {
519 4169         9224 $i = $k + 1;
520             }
521             else
522             {
523 4066         9004 $j = $k - 1;
524             }
525             } until $i > $j;
526              
527 11         29 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__