File Coverage

blib/lib/List/Util/PP.pm
Criterion Covered Total %
statement 248 273 90.8
branch 83 108 76.8
condition 47 75 62.6
subroutine 47 47 100.0
pod 33 33 100.0
total 458 536 85.4


line stmt bran cond sub pod time code
1             package List::Util::PP;
2 24     24   1055459 use strict;
  24         216  
  24         592  
3 24     24   106 use warnings;
  24         34  
  24         481  
4 24     24   1270 use Exporter ();
  24         47  
  24         1961  
5              
6             our $VERSION = '1.500011';
7             $VERSION =~ tr/_//d;
8              
9             our @EXPORT_OK;
10             BEGIN {
11 24     24   2027 @EXPORT_OK = qw(
12             all any first none notall
13             min max minstr maxstr
14             product reductions reduce sum sum0
15             sample shuffle
16             uniq uniqnum uniqint uniqstr
17             pairs unpairs pairkeys pairvalues pairmap pairgrep pairfirst
18             head tail
19             zip zip_longest zip_shortest
20             mesh mesh_longest mesh_shortest
21             );
22             }
23              
24             my $rand = do { our $RAND };
25             *RAND = *List::Util::RAND;
26             our $RAND;
27             $RAND = $rand
28             if !defined $RAND;
29              
30             sub import {
31 25     25   232 my $pkg = caller;
32              
33             # (RT88848) Touch the caller's $a and $b, to avoid the warning of
34             # Name "main::a" used only once: possible typo" warning
35 24     24   140 no strict 'refs';
  24         58  
  24         5130  
36 25         44 ${"${pkg}::a"} = ${"${pkg}::a"};
  25         60  
  25         125  
37 25         31 ${"${pkg}::b"} = ${"${pkg}::b"};
  25         46  
  25         73  
38              
39             # May be imported by List::Util if very old version is installed, which
40             # expects default exports
41 25 50 33     117 if ($pkg eq 'List::Util' && @_ < 2) {
42             package #hide from PAUSE
43             List::Util;
44 0         0 return __PACKAGE__->import(qw(first min max minstr maxstr reduce sum shuffle));
45             }
46              
47 25         13585 goto &Exporter::import;
48             }
49              
50             sub reduce (&@) {
51 32     32 1 12687 my $f = shift;
52 32 100 100     93 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  28         63  
  25         79  
53 7         38 require Carp;
54 7         541 Carp::croak("Not a subroutine reference");
55             }
56              
57 25 100       56 return shift unless @_ > 1;
58              
59 23         42 my $pkg = caller;
60 23         30 my $a = shift;
61              
62 24     24   154 no strict 'refs';
  24         39  
  24         4404  
63 23         28 local *{"${pkg}::a"} = \$a;
  23         67  
64 23         32 my $glob_b = \*{"${pkg}::b"};
  23         40  
65              
66 23         43 foreach my $b (@_) {
67 92         271 local *$glob_b = \$b;
68 92         131 $a = $f->();
69             }
70              
71 21         117 $a;
72             }
73              
74             sub reductions (&@) {
75 5     5 1 1099 my $f = shift;
76 5 50 33     14 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         10  
  5         13  
77 0         0 require Carp;
78 0         0 Carp::croak("Not a subroutine reference");
79             }
80              
81 5 100       17 return unless @_;
82 4 50       9 return shift unless @_ > 1;
83              
84 4         6 my $pkg = caller;
85 4         5 my $a = shift;
86              
87 24     24   151 no strict 'refs';
  24         62  
  24         29288  
88 4         6 local *{"${pkg}::a"} = \$a;
  4         10  
89 4         6 my $glob_b = \*{"${pkg}::b"};
  4         8  
90              
91 4         8 my @o = $a;
92              
93 4         6 foreach my $b (@_) {
94 13         15 local *$glob_b = \$b;
95 13         19 $a = $f->();
96 12         36 push @o, $a;
97             }
98              
99 3         10 @o;
100             }
101              
102             sub first (&@) {
103 23     23 1 8464 my $f = shift;
104 23 100 100     69 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  20         45  
  18         58  
105 5         22 require Carp;
106 5         422 Carp::croak("Not a subroutine reference");
107             }
108              
109             $f->() and return $_
110 18   100     51 foreach @_;
111              
112 5         38 undef;
113             }
114              
115             sub sum (@) {
116 22 100   22 1 11886 return undef unless @_;
117 21         30 my $s = 0;
118 21         94 $s += $_ foreach @_;
119 21         718 return $s;
120             }
121              
122             sub min (@) {
123 16 50   16 1 5844 return undef unless @_;
124 16         27 my $min = shift;
125             $_ < $min and $min = $_
126 16   66     81 foreach @_;
127 16         351 return $min;
128             }
129              
130             sub max (@) {
131 21 100   21 1 6039 return undef unless @_;
132 19         29 my $max = shift;
133             $_ > $max and $max = $_
134 19   66     86 foreach @_;
135 19         532 return $max;
136             }
137              
138             sub minstr (@) {
139 4 50   4 1 1997 return undef unless @_;
140 4         7 my $min = shift;
141             $_ lt $min and $min = $_
142 4   66     21 foreach @_;
143 4         10 return $min;
144             }
145              
146             sub maxstr (@) {
147 4 50   4 1 2053 return undef unless @_;
148 4         7 my $max = shift;
149             $_ gt $max and $max = $_
150 4   66     21 foreach @_;
151 4         9 return $max;
152             }
153              
154             sub shuffle (@) {
155 6     6 1 4084 sample(scalar @_, @_);
156             }
157              
158             sub sample ($@) {
159 16     16 1 4706 my $num = shift;
160 16         44 my @i = (0 .. $#_);
161 16 100       39 $num = @_ if $num > @_;
162 16 100       165 my @o = defined $RAND ? (map +(splice @i, $RAND->($#i), 1), 1 .. $num)
163             : (map +(splice @i, rand($#i), 1), 1 .. $num);
164 16         124 @_[@o];
165             }
166              
167             sub all (&@) {
168 4     4 1 967 my $f = shift;
169 4 50 33     19 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         8  
  4         17  
170 0         0 require Carp;
171 0         0 Carp::croak("Not a subroutine reference");
172             }
173              
174             $f->() or return !!0
175 4   100     17 foreach @_;
176 3         27 return !!1;
177             }
178              
179             sub any (&@) {
180 5     5 1 1202 my $f = shift;
181 5 50 33     33 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         11  
  5         24  
182 0         0 require Carp;
183 0         0 Carp::croak("Not a subroutine reference");
184             }
185              
186             $f->() and return !!1
187 5   100     16 foreach @_;
188 2         13 return !!0;
189             }
190              
191             sub none (&@) {
192 4     4 1 586 my $f = shift;
193 4 50 33     16 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         8  
  4         16  
194 0         0 require Carp;
195 0         0 Carp::croak("Not a subroutine reference");
196             }
197              
198             $f->() and return !!0
199 4   100     12 foreach @_;
200 2         12 return !!1;
201             }
202              
203             sub notall (&@) {
204 4     4 1 561 my $f = shift;
205 4 50 33     14 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         8  
  4         16  
206 0         0 require Carp;
207 0         0 Carp::croak("Not a subroutine reference");
208             }
209              
210             $f->() or return !!1
211 4   100     11 foreach @_;
212 3         24 return !!0;
213             }
214              
215             sub product (@) {
216 25     25 1 11390 my $p = 1;
217 25         113 $p *= $_ foreach @_;
218 25         682 return $p;
219             }
220              
221             sub sum0 (@) {
222 3     3 1 1541 my $s = 0;
223 3         8 $s += $_ foreach @_;
224 3         5 return $s;
225             }
226              
227             sub pairs (@) {
228 3 100   3 1 16066 if (@_ % 2) {
229 1         125 warnings::warnif('misc', 'Odd number of elements in pairs');
230             }
231              
232             return
233 3         26 map { bless [ @_[$_, $_ + 1] ], 'List::Util::PP::_Pair' }
  7         44  
234             map $_*2,
235             0 .. int($#_/2);
236             }
237              
238             sub unpairs (@) {
239 3     3 1 592 map @{$_}[0,1], @_;
  7         24  
240             }
241              
242             sub pairkeys (@) {
243 1 50   1 1 7 if (@_ % 2) {
244 0         0 warnings::warnif('misc', 'Odd number of elements in pairkeys');
245             }
246              
247             return
248 1         14 map $_[$_*2],
249             0 .. int($#_/2);
250             }
251              
252             sub pairvalues (@) {
253 1 50   1 1 5 if (@_ % 2) {
254 0         0 require Carp;
255 0         0 warnings::warnif('misc', 'Odd number of elements in pairvalues');
256             }
257              
258             return
259 1         11 map $_[$_*2 + 1],
260             0 .. int($#_/2);
261             }
262              
263             sub pairmap (&@) {
264 11     11 1 4131 my $f = shift;
265 11 50 33     38 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  11         17  
  11         40  
266 0         0 require Carp;
267 0         0 Carp::croak("Not a subroutine reference");
268             }
269              
270 11 100       30 if (@_ % 2) {
271 1         97 warnings::warnif('misc', 'Odd number of elements in pairmap');
272             }
273              
274 11         23 my $pkg = caller;
275 24     24   200 no strict 'refs';
  24         53  
  24         4819  
276 11         13 my $glob_a = \*{"${pkg}::a"};
  11         29  
277 11         17 my $glob_b = \*{"${pkg}::b"};
  11         18  
278              
279             return
280             map {
281 11         71 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  30         435  
282 30         51 $f->();
283             }
284             map $_*2,
285             0 .. int($#_/2);
286             }
287              
288             sub pairgrep (&@) {
289 7     7 1 1384 my $f = shift;
290 7 50 33     25 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  7         15  
  7         29  
291 0         0 require Carp;
292 0         0 Carp::croak("Not a subroutine reference");
293             }
294              
295 7 100       22 if (@_ % 2) {
296 2         317 warnings::warnif('misc', 'Odd number of elements in pairgrep');
297             }
298              
299 7         91 my $pkg = caller;
300 24     24   160 no strict 'refs';
  24         49  
  24         4754  
301 7         12 my $glob_a = \*{"${pkg}::a"};
  7         24  
302 7         9 my $glob_b = \*{"${pkg}::b"};
  7         15  
303              
304             return
305             map {
306 7         37 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  18         77  
307 18 100       32 $f->() ? (wantarray ? @_[$_,$_+1] : 1) : ();
    100          
308             }
309             map $_*2,
310             0 .. int ($#_/2);
311             }
312              
313             sub pairfirst (&@) {
314 5     5 1 1164 my $f = shift;
315 5 50 33     21 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         11  
  5         20  
316 0         0 require Carp;
317 0         0 Carp::croak("Not a subroutine reference");
318             }
319              
320 5 50       15 if (@_ % 2) {
321 0         0 warnings::warnif('misc', 'Odd number of elements in pairfirst');
322             }
323              
324 5         10 my $pkg = caller;
325 24     24   150 no strict 'refs';
  24         43  
  24         28055  
326 5         7 my $glob_a = \*{"${pkg}::a"};
  5         16  
327 5         8 my $glob_b = \*{"${pkg}::b"};
  5         7  
328              
329 5         40 foreach my $i (map $_*2, 0 .. int($#_/2)) {
330 13         50 local (*$glob_a, *$glob_b) = \( @_[$i,$i+1] );
331 13 100       23 return wantarray ? @_[$i,$i+1] : 1
    100          
332             if $f->();
333             }
334 2         14 return ();
335             }
336              
337 1     1   10 sub List::Util::PP::_Pair::key { $_[0][0] }
338 1     1   5 sub List::Util::PP::_Pair::value { $_[0][1] }
339 2     2   4 sub List::Util::PP::_Pair::TO_JSON { [ @{$_[0]} ] }
  2         16  
340              
341             sub uniq (@) {
342 5     5 1 3526 my %seen;
343             my $undef;
344 5 100       44 my @uniq = grep defined($_) ? !$seen{$_}++ : !$undef++, @_;
345 5         217 @uniq;
346             }
347              
348             sub uniqnum (@) {
349 838     838 1 4968306 my %seen;
350             my $sv;
351 838         5786 require B;
352 838         4144 my $b = B::svref_2object(\$sv);
353             my @uniq =
354             grep {
355 333453         361707 my $nv = $_;
356 333453         331366 my $k;
357 333453 50 66     477684 if (ref $nv && defined &overload::ov_method && defined &overload::mycan) {
      66        
358 3         5 my $package = ref $nv;
359             # also covers Math::BigInt and Math::BigFloat
360 3 50 33     14 if (UNIVERSAL::isa($nv, 'Math::BigInt')) {
    50          
    0          
361 0         0 $k = $nv->bstr;
362             }
363             elsif(my $method
364             = overload::ov_method(overload::mycan($package, '(0+'), $package)
365             || overload::ov_method(overload::mycan($package, '""'), $package)
366             || overload::ov_method(overload::mycan($package, 'bool'), $package)
367             ) {
368 3         78 $nv = $nv->$method(undef, !!0);
369             }
370             elsif (
371             my $nomethod = overload::ov_method(overload::mycan($package, '(nomethod'), $package)
372             ) {
373 0         0 $nv = $nv->$nomethod(undef, undef, '0+');
374             }
375             }
376              
377 333453 50 100     938035 if (defined $k) {
    50          
    100          
    100          
    100          
378             }
379             elsif (ref $nv) {
380 0         0 $k = 'R' . 0+$nv;
381             }
382             elsif ($nv == 0) {
383 29788         31206 $k = '0';
384             }
385             elsif ($nv != $nv || $nv == 9**9**9) {
386 215         319 $k = sprintf '%f', $nv;
387             }
388             elsif (int($nv) != $nv) {
389 93167         126533 $k = 'N' . pack('F', $nv);
390             }
391             else {
392 210283         227882 $sv = $nv + 0;
393 210283         277611 my $flags = $b->FLAGS;
394 210283 100       299906 if ($flags & B::SVf_IVisUV()) {
    100          
    50          
395 774         1379 $k = sprintf '%u', $nv;
396             }
397             elsif ($flags & B::SVf_IOK()) {
398 192796         273329 $k = sprintf '%d', $nv;
399             }
400             elsif ($flags & B::SVf_NOK()) {
401 16713         118128 $k = sprintf '%.0f', $nv;
402             }
403             else {
404 0         0 $k = $nv;
405             }
406             }
407 333453         597660 !$seen{$k}++;
408             }
409             map +(defined($_) ? $_
410 838 100       100712 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2         289  
  2         15  
411             @_;
412 838         24856 @uniq;
413             }
414              
415             sub uniqint (@) {
416 9     9 1 2486 my %seen;
417             my @uniq =
418             map +(
419             ref $_ ? $_ : int($_)
420             ),
421             grep {
422             !$seen{
423 18 50       138 /\A[0-9]+\z/ ? $_
    100          
424             : $_ > 0 ? sprintf '%u', $_
425             : sprintf '%d', $_
426             }++;
427             }
428             map +(defined($_) ? $_
429 9 100       31 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2 100       189  
  2         15  
430             @_;
431 9         57 @uniq;
432             }
433              
434             sub uniqstr (@) {
435 13     13 1 2595 my %seen;
436             my @uniq =
437             grep !$seen{$_}++,
438             map +(defined($_) ? $_
439 13 100       109 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); '' }),
  2         288  
  2         20  
440             @_;
441 13         78 @uniq;
442             }
443              
444             sub head ($@) {
445 11     11 1 9259 my $size = shift;
446             return @_
447 11 100       29 if $size > @_;
448 8 100       35 @_[ 0 .. ( $size >= 0 ? $size - 1 : $#_ + $size ) ];
449             }
450              
451             sub tail ($@) {
452 9     9 1 7171 my $size = shift;
453             return @_
454 9 100       24 if $size > @_;
455 8 100       34 @_[ ( $size >= 0 ? ($#_ - ($size-1) ) : 0 - $size ) .. $#_ ];
456             }
457              
458             sub zip_longest {
459             map {
460 6   100 6 1 96 my $idx = $_;
  8         9  
461 8         33 [ map $_->[$idx], @_ ];
462             } ( 0 .. max(map $#$_, @_) || -1 )
463             }
464              
465             sub zip_shortest {
466             map {
467 1   50 1 1 8 my $idx = $_;
  2         3  
468 2         11 [ map $_->[$idx], @_ ];
469             } ( 0 .. min(map $#$_, @_) || -1 )
470             }
471              
472             *zip = \&zip_longest;
473              
474             sub mesh_longest {
475             map {
476 6   100 6 1 96 my $idx = $_;
  8         9  
477 8         25 map $_->[$idx], @_;
478             } ( 0 .. max(map $#$_, @_) || -1 )
479             }
480              
481             sub mesh_shortest {
482             map {
483 1   50 1 1 5 my $idx = $_;
  2         2  
484 2         8 map $_->[$idx], @_;
485             } ( 0 .. min(map $#$_, @_) || -1 )
486             }
487              
488             *mesh = \&mesh_longest;
489              
490             1;
491              
492             __END__