File Coverage

blib/lib/List/Util/PP.pm
Criterion Covered Total %
statement 248 273 90.8
branch 83 108 76.8
condition 44 72 61.1
subroutine 47 47 100.0
pod 33 33 100.0
total 455 533 85.3


line stmt bran cond sub pod time code
1             package List::Util::PP;
2 24     24   2124675 use strict;
  24         53  
  24         927  
3 24     24   117 use warnings;
  24         44  
  24         1526  
4 24     24   190 use Exporter ();
  24         48  
  24         3384  
5              
6             our $VERSION = '1.500014';
7             $VERSION =~ tr/_//d;
8              
9             our @EXPORT_OK;
10             BEGIN {
11 24     24   2742 @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   292 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   191 no strict 'refs';
  24         79  
  24         7090  
36 25         49 ${"${pkg}::a"} = ${"${pkg}::a"};
  25         189  
  25         133  
37 25         78 ${"${pkg}::b"} = ${"${pkg}::b"};
  25         69  
  25         106  
38              
39             # May be imported by List::Util if very old version is installed, which
40             # expects default exports
41 25 50 33     119 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         18644 goto &Exporter::import;
48             }
49              
50             sub reduce (&@) {
51 32     32 1 561189 my $f = shift;
52 32 100 100     106 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  28         61  
  25         83  
53 7         77 require Carp;
54 7         590 Carp::croak("Not a subroutine reference");
55             }
56              
57 25 100       53 return shift unless @_ > 1;
58              
59 23         36 my $pkg = caller;
60 23         29 my $a = shift;
61              
62 24     24   173 no strict 'refs';
  24         76  
  24         5944  
63 23         27 local *{"${pkg}::a"} = \$a;
  23         68  
64 23         57 my $glob_b = \*{"${pkg}::b"};
  23         50  
65              
66 23         39 foreach my $b (@_) {
67 92         238 local *$glob_b = \$b;
68 92         119 $a = $f->();
69             }
70              
71 21         102 $a;
72             }
73              
74             sub reductions (&@) {
75 5     5 1 239121 my $f = shift;
76 5 50 33     25 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         12  
  5         23  
77 0         0 require Carp;
78 0         0 Carp::croak("Not a subroutine reference");
79             }
80              
81 5 100       24 return unless @_;
82 4 50       12 return shift unless @_ > 1;
83              
84 4         11 my $pkg = caller;
85 4         7 my $a = shift;
86              
87 24     24   170 no strict 'refs';
  24         54  
  24         39368  
88 4         9 local *{"${pkg}::a"} = \$a;
  4         19  
89 4         8 my $glob_b = \*{"${pkg}::b"};
  4         11  
90              
91 4         11 my @o = $a;
92              
93 4         11 foreach my $b (@_) {
94 13         25 local *$glob_b = \$b;
95 13         28 $a = $f->();
96 12         49 push @o, $a;
97             }
98              
99 3         15 @o;
100             }
101              
102             sub first (&@) {
103 23     23 1 674308 my $f = shift;
104 23 100 100     82 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  20         56  
  18         64  
105 5         23 require Carp;
106 5         450 Carp::croak("Not a subroutine reference");
107             }
108              
109             $f->() and return $_
110 18   100     59 foreach @_;
111              
112 5         39 undef;
113             }
114              
115             sub sum (@) {
116 22 100   22 1 367197 return undef unless @_;
117 21         40 my $s = 0;
118 21         149 $s += $_ foreach @_;
119 21         1558 return $s;
120             }
121              
122             sub min (@) {
123 16 50   16 1 319387 return undef unless @_;
124 16         36 my $min = shift;
125             $_ < $min and $min = $_
126 16   66     123 foreach @_;
127 16         770 return $min;
128             }
129              
130             sub max (@) {
131 21 100   21 1 243354 return undef unless @_;
132 19         36 my $max = shift;
133             $_ > $max and $max = $_
134 19   66     95 foreach @_;
135 19         640 return $max;
136             }
137              
138             sub minstr (@) {
139 4 50   4 1 244178 return undef unless @_;
140 4         9 my $min = shift;
141             $_ lt $min and $min = $_
142 4   66     45 foreach @_;
143 4         15 return $min;
144             }
145              
146             sub maxstr (@) {
147 4 50   4 1 197314 return undef unless @_;
148 4         10 my $max = shift;
149             $_ gt $max and $max = $_
150 4   66     58 foreach @_;
151 4         14 return $max;
152             }
153              
154             sub shuffle (@) {
155 6     6 1 207629 sample(scalar @_, @_);
156             }
157              
158             sub sample ($@) {
159 16     16 1 185095 my $num = shift;
160 16         49 my @i = (0 .. $#_);
161 16 100       54 $num = @_ if $num > @_;
162 16 100       344 my @o = defined $RAND ? (map +(splice @i, $RAND->(scalar @i), 1), 1 .. $num)
163             : (map +(splice @i, rand(scalar @i), 1), 1 .. $num);
164 16         165 @_[@o];
165             }
166              
167             sub all (&@) {
168 4     4 1 1160 my $f = shift;
169 4 50 33     25 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         10  
  4         25  
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         34 return !!1;
177             }
178              
179             sub any (&@) {
180 5     5 1 320769 my $f = shift;
181 5 50 33     33 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         14  
  5         33  
182 0         0 require Carp;
183 0         0 Carp::croak("Not a subroutine reference");
184             }
185              
186             $f->() and return !!1
187 5   100     23 foreach @_;
188 2         19 return !!0;
189             }
190              
191             sub none (&@) {
192 4     4 1 868 my $f = shift;
193 4 50 33     25 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         11  
  4         24  
194 0         0 require Carp;
195 0         0 Carp::croak("Not a subroutine reference");
196             }
197              
198             $f->() and return !!0
199 4   100     15 foreach @_;
200 2         18 return !!1;
201             }
202              
203             sub notall (&@) {
204 4     4 1 860 my $f = shift;
205 4 50 33     21 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         26  
  4         24  
206 0         0 require Carp;
207 0         0 Carp::croak("Not a subroutine reference");
208             }
209              
210             $f->() or return !!1
211 4   100     17 foreach @_;
212 3         35 return !!0;
213             }
214              
215             sub product (@) {
216 25     25 1 326690 my $p = 1;
217 25         106 $p *= $_ foreach @_;
218 25         980 return $p;
219             }
220              
221             sub sum0 (@) {
222 3     3 1 162629 my $s = 0;
223 3         12 $s += $_ foreach @_;
224 3         22 return $s;
225             }
226              
227             sub pairs (@) {
228 3 100   3 1 24138 if (@_ % 2) {
229 1         160 warnings::warnif('misc', 'Odd number of elements in pairs');
230             }
231              
232             return
233 3         24 map { bless [ @_[$_, $_ + 1] ], 'List::Util::PP::_Pair' }
  7         52  
234             map $_*2,
235             0 .. int($#_/2);
236             }
237              
238             sub unpairs (@) {
239 3     3 1 952 map @{$_}[0,1], @_;
  7         35  
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 6 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         12 map $_[$_*2 + 1],
260             0 .. int($#_/2);
261             }
262              
263             sub pairmap (&@) {
264 11     11 1 7680 my $f = shift;
265 11 50 33     53 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  11         27  
  11         53  
266 0         0 require Carp;
267 0         0 Carp::croak("Not a subroutine reference");
268             }
269              
270 11 100       38 if (@_ % 2) {
271 1         131 warnings::warnif('misc', 'Odd number of elements in pairmap');
272             }
273              
274 11         33 my $pkg = caller;
275 24     24   215 no strict 'refs';
  24         49  
  24         6897  
276 11         17 my $glob_a = \*{"${pkg}::a"};
  11         43  
277 11         20 my $glob_b = \*{"${pkg}::b"};
  11         32  
278              
279             return
280             map {
281 11         66 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  30         611  
282 30         75 $f->();
283             }
284             map $_*2,
285             0 .. int($#_/2);
286             }
287              
288             sub pairgrep (&@) {
289 7     7 1 239727 my $f = shift;
290 7 50 33     41 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  7         16  
  7         36  
291 0         0 require Carp;
292 0         0 Carp::croak("Not a subroutine reference");
293             }
294              
295 7 100       38 if (@_ % 2) {
296 2         387 warnings::warnif('misc', 'Odd number of elements in pairgrep');
297             }
298              
299 7         30 my $pkg = caller;
300 24     24   262 no strict 'refs';
  24         90  
  24         7212  
301 7         13 my $glob_a = \*{"${pkg}::a"};
  7         30  
302 7         13 my $glob_b = \*{"${pkg}::b"};
  7         19  
303              
304             return
305             map {
306 7         46 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  18         97  
307 18 100       44 $f->() ? (wantarray ? @_[$_,$_+1] : 1) : ();
    100          
308             }
309             map $_*2,
310             0 .. int ($#_/2);
311             }
312              
313             sub pairfirst (&@) {
314 5     5 1 1662 my $f = shift;
315 5 50 33     25 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         14  
  5         33  
316 0         0 require Carp;
317 0         0 Carp::croak("Not a subroutine reference");
318             }
319              
320 5 50       20 if (@_ % 2) {
321 0         0 warnings::warnif('misc', 'Odd number of elements in pairfirst');
322             }
323              
324 5         13 my $pkg = caller;
325 24     24   175 no strict 'refs';
  24         54  
  24         38680  
326 5         10 my $glob_a = \*{"${pkg}::a"};
  5         23  
327 5         10 my $glob_b = \*{"${pkg}::b"};
  5         16  
328              
329 5         36 foreach my $i (map $_*2, 0 .. int($#_/2)) {
330 13         64 local (*$glob_a, *$glob_b) = \( @_[$i,$i+1] );
331 13 100       33 return wantarray ? @_[$i,$i+1] : 1
    100          
332             if $f->();
333             }
334 2         26 return ();
335             }
336              
337 1     1   12 sub List::Util::PP::_Pair::key { $_[0][0] }
338 1     1   7 sub List::Util::PP::_Pair::value { $_[0][1] }
339 2     2   7 sub List::Util::PP::_Pair::TO_JSON { [ @{$_[0]} ] }
  2         16  
340              
341             sub uniq (@) {
342 5     5 1 194678 my %seen;
343             my $undef;
344 5 100       56 my @uniq = grep defined($_) ? !$seen{$_}++ : !$undef++, @_;
345 5         168 @uniq;
346             }
347              
348             sub uniqnum (@) {
349 838     838 1 6398639 my %seen;
350             my $sv;
351 838         9002 require B;
352 838         5060 my $b = B::svref_2object(\$sv);
353             my @uniq =
354             grep {
355 333453         417419 my $nv = $_;
356 333453         390348 my $k;
357 333453 50 66     597968 if (ref $nv && defined &overload::ov_method && defined &overload::mycan) {
      66        
358 3         7 my $package = ref $nv;
359             # also covers Math::BigInt and Math::BigFloat
360 3 50 33     29 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         126 $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       834142 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         38013 $k = '0';
384             }
385             elsif ($nv*0 != $nv*0) {
386 309         466 $k = sprintf '%f', $nv;
387             }
388             elsif (int($nv) != $nv) {
389 93167         145790 $k = 'N' . pack('F', $nv);
390             }
391             else {
392 210189         253165 $sv = $nv + 0;
393 210189         328051 my $flags = $b->FLAGS;
394 210189 100       373817 if ($flags & B::SVf_IVisUV()) {
    100          
    50          
395 1094         2226 $k = sprintf '%u', $nv;
396             }
397             elsif ($flags & B::SVf_IOK()) {
398 192756         304257 $k = sprintf '%d', $nv;
399             }
400             elsif ($flags & B::SVf_NOK()) {
401 16339         162111 $k = sprintf '%.0f', $nv;
402             }
403             else {
404 0         0 $k = $nv;
405             }
406             }
407 333453         623813 !$seen{$k}++;
408             }
409             map +(defined($_) ? $_
410 838 100       156979 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2         453  
  2         24  
411             @_;
412 838         34858 @uniq;
413             }
414              
415             sub uniqint (@) {
416 9     9 1 1880 my %seen;
417             my @uniq =
418             map +(
419             ref $_ ? $_ : int($_)
420             ),
421             grep {
422             !$seen{
423 18 50       118 /\A[0-9]+\z/ ? $_
    100          
424             : $_ > 0 ? sprintf '%u', $_
425             : sprintf '%d', $_
426             }++;
427             }
428             map +(defined($_) ? $_
429 9 100       30 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2 100       225  
  2         14  
430             @_;
431 9         39 @uniq;
432             }
433              
434             sub uniqstr (@) {
435 13     13 1 179617 my %seen;
436             my @uniq =
437             grep !$seen{$_}++,
438             map +(defined($_) ? $_
439 13 100       130 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); '' }),
  2         507  
  2         29  
440             @_;
441 13         96 @uniq;
442             }
443              
444             sub head ($@) {
445 11     11 1 372416 my $size = shift;
446             return @_
447 11 100       53 if $size > @_;
448 8 100       38 @_[ 0 .. ( $size >= 0 ? $size - 1 : $#_ + $size ) ];
449             }
450              
451             sub tail ($@) {
452 9     9 1 10911 my $size = shift;
453             return @_
454 9 100       29 if $size > @_;
455 8 100       50 @_[ ( $size >= 0 ? ($#_ - ($size-1) ) : 0 - $size ) .. $#_ ];
456             }
457              
458             sub zip_longest {
459             map {
460 6   100 6 1 142605 my $idx = $_;
  8         12  
461 8         44 [ map $_->[$idx], @_ ];
462             } ( 0 .. max(map $#$_, @_) || -1 )
463             }
464              
465             sub zip_shortest {
466             map {
467 1   50 1 1 6 my $idx = $_;
  2         3  
468 2         13 [ 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 229055 my $idx = $_;
  8         11  
477 8         46 map $_->[$idx], @_;
478             } ( 0 .. max(map $#$_, @_) || -1 )
479             }
480              
481             sub mesh_shortest {
482             map {
483 1   50 1 1 8 my $idx = $_;
  2         5  
484 2         13 map $_->[$idx], @_;
485             } ( 0 .. min(map $#$_, @_) || -1 )
486             }
487              
488             *mesh = \&mesh_longest;
489              
490             1;
491              
492             __END__