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   1102102 use strict;
  24         223  
  24         680  
3 24     24   108 use warnings;
  24         44  
  24         582  
4 24     24   99 use Exporter ();
  24         36  
  24         2055  
5              
6             our $VERSION = '1.500012';
7             $VERSION =~ tr/_//d;
8              
9             our @EXPORT_OK;
10             BEGIN {
11 24     24   2096 @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   269 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   136 no strict 'refs';
  24         61  
  24         5013  
36 25         42 ${"${pkg}::a"} = ${"${pkg}::a"};
  25         57  
  25         132  
37 25         39 ${"${pkg}::b"} = ${"${pkg}::b"};
  25         51  
  25         83  
38              
39             # May be imported by List::Util if very old version is installed, which
40             # expects default exports
41 25 50 33     137 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         15969 goto &Exporter::import;
48             }
49              
50             sub reduce (&@) {
51 32     32 1 13737 my $f = shift;
52 32 100 100     127 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  28         65  
  25         80  
53 7         41 require Carp;
54 7         595 Carp::croak("Not a subroutine reference");
55             }
56              
57 25 100       54 return shift unless @_ > 1;
58              
59 23         57 my $pkg = caller;
60 23         32 my $a = shift;
61              
62 24     24   174 no strict 'refs';
  24         40  
  24         4390  
63 23         30 local *{"${pkg}::a"} = \$a;
  23         71  
64 23         29 my $glob_b = \*{"${pkg}::b"};
  23         45  
65              
66 23         43 foreach my $b (@_) {
67 92         303 local *$glob_b = \$b;
68 92         144 $a = $f->();
69             }
70              
71 21         127 $a;
72             }
73              
74             sub reductions (&@) {
75 5     5 1 1120 my $f = shift;
76 5 50 33     15 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         8  
  5         17  
77 0         0 require Carp;
78 0         0 Carp::croak("Not a subroutine reference");
79             }
80              
81 5 100       18 return unless @_;
82 4 50       11 return shift unless @_ > 1;
83              
84 4         6 my $pkg = caller;
85 4         7 my $a = shift;
86              
87 24     24   153 no strict 'refs';
  24         55  
  24         28592  
88 4         5 local *{"${pkg}::a"} = \$a;
  4         14  
89 4         5 my $glob_b = \*{"${pkg}::b"};
  4         9  
90              
91 4         7 my @o = $a;
92              
93 4         7 foreach my $b (@_) {
94 13         16 local *$glob_b = \$b;
95 13         21 $a = $f->();
96 12         34 push @o, $a;
97             }
98              
99 3         12 @o;
100             }
101              
102             sub first (&@) {
103 23     23 1 8384 my $f = shift;
104 23 100 100     69 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  20         41  
  18         63  
105 5         24 require Carp;
106 5         433 Carp::croak("Not a subroutine reference");
107             }
108              
109             $f->() and return $_
110 18   100     48 foreach @_;
111              
112 5         36 undef;
113             }
114              
115             sub sum (@) {
116 22 100   22 1 13071 return undef unless @_;
117 21         30 my $s = 0;
118 21         118 $s += $_ foreach @_;
119 21         1074 return $s;
120             }
121              
122             sub min (@) {
123 16 50   16 1 5831 return undef unless @_;
124 16         30 my $min = shift;
125             $_ < $min and $min = $_
126 16   66     87 foreach @_;
127 16         347 return $min;
128             }
129              
130             sub max (@) {
131 21 100   21 1 6155 return undef unless @_;
132 19         34 my $max = shift;
133             $_ > $max and $max = $_
134 19   66     88 foreach @_;
135 19         534 return $max;
136             }
137              
138             sub minstr (@) {
139 4 50   4 1 2012 return undef unless @_;
140 4         7 my $min = shift;
141             $_ lt $min and $min = $_
142 4   66     21 foreach @_;
143 4         9 return $min;
144             }
145              
146             sub maxstr (@) {
147 4 50   4 1 2256 return undef unless @_;
148 4         7 my $max = shift;
149             $_ gt $max and $max = $_
150 4   66     21 foreach @_;
151 4         10 return $max;
152             }
153              
154             sub shuffle (@) {
155 6     6 1 3921 sample(scalar @_, @_);
156             }
157              
158             sub sample ($@) {
159 16     16 1 5647 my $num = shift;
160 16         57 my @i = (0 .. $#_);
161 16 100       44 $num = @_ if $num > @_;
162 16 100       171 my @o = defined $RAND ? (map +(splice @i, $RAND->($#i), 1), 1 .. $num)
163             : (map +(splice @i, rand($#i), 1), 1 .. $num);
164 16         131 @_[@o];
165             }
166              
167             sub all (&@) {
168 4     4 1 1192 my $f = shift;
169 4 50 33     18 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         7  
  4         18  
170 0         0 require Carp;
171 0         0 Carp::croak("Not a subroutine reference");
172             }
173              
174             $f->() or return !!0
175 4   100     13 foreach @_;
176 3         27 return !!1;
177             }
178              
179             sub any (&@) {
180 5     5 1 1268 my $f = shift;
181 5 50 33     22 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         10  
  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     17 foreach @_;
188 2         14 return !!0;
189             }
190              
191             sub none (&@) {
192 4     4 1 658 my $f = shift;
193 4 50 33     15 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         9  
  4         15  
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         13 return !!1;
201             }
202              
203             sub notall (&@) {
204 4     4 1 598 my $f = shift;
205 4 50 33     15 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         7  
  4         17  
206 0         0 require Carp;
207 0         0 Carp::croak("Not a subroutine reference");
208             }
209              
210             $f->() or return !!1
211 4   100     13 foreach @_;
212 3         25 return !!0;
213             }
214              
215             sub product (@) {
216 25     25 1 12579 my $p = 1;
217 25         118 $p *= $_ foreach @_;
218 25         699 return $p;
219             }
220              
221             sub sum0 (@) {
222 3     3 1 1261 my $s = 0;
223 3         7 $s += $_ foreach @_;
224 3         6 return $s;
225             }
226              
227             sub pairs (@) {
228 3 100   3 1 15575 if (@_ % 2) {
229 1         100 warnings::warnif('misc', 'Odd number of elements in pairs');
230             }
231              
232             return
233 3         24 map { bless [ @_[$_, $_ + 1] ], 'List::Util::PP::_Pair' }
  7         42  
234             map $_*2,
235             0 .. int($#_/2);
236             }
237              
238             sub unpairs (@) {
239 3     3 1 465 map @{$_}[0,1], @_;
  7         30  
240             }
241              
242             sub pairkeys (@) {
243 1 50   1 1 8 if (@_ % 2) {
244 0         0 warnings::warnif('misc', 'Odd number of elements in pairkeys');
245             }
246              
247             return
248 1         13 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         11 map $_[$_*2 + 1],
260             0 .. int($#_/2);
261             }
262              
263             sub pairmap (&@) {
264 11     11 1 3525 my $f = shift;
265 11 50 33     40 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  11         18  
  11         43  
266 0         0 require Carp;
267 0         0 Carp::croak("Not a subroutine reference");
268             }
269              
270 11 100       77 if (@_ % 2) {
271 1         105 warnings::warnif('misc', 'Odd number of elements in pairmap');
272             }
273              
274 11         21 my $pkg = caller;
275 24     24   207 no strict 'refs';
  24         44  
  24         4861  
276 11         17 my $glob_a = \*{"${pkg}::a"};
  11         36  
277 11         15 my $glob_b = \*{"${pkg}::b"};
  11         26  
278              
279             return
280             map {
281 11         55 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  30         389  
282 30         51 $f->();
283             }
284             map $_*2,
285             0 .. int($#_/2);
286             }
287              
288             sub pairgrep (&@) {
289 7     7 1 1575 my $f = shift;
290 7 50 33     24 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  7         14  
  7         28  
291 0         0 require Carp;
292 0         0 Carp::croak("Not a subroutine reference");
293             }
294              
295 7 100       23 if (@_ % 2) {
296 2         297 warnings::warnif('misc', 'Odd number of elements in pairgrep');
297             }
298              
299 7         89 my $pkg = caller;
300 24     24   162 no strict 'refs';
  24         53  
  24         4623  
301 7         8 my $glob_a = \*{"${pkg}::a"};
  7         25  
302 7         9 my $glob_b = \*{"${pkg}::b"};
  7         18  
303              
304             return
305             map {
306 7         38 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  18         76  
307 18 100       36 $f->() ? (wantarray ? @_[$_,$_+1] : 1) : ();
    100          
308             }
309             map $_*2,
310             0 .. int ($#_/2);
311             }
312              
313             sub pairfirst (&@) {
314 5     5 1 1093 my $f = shift;
315 5 50 33     21 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         10  
  5         22  
316 0         0 require Carp;
317 0         0 Carp::croak("Not a subroutine reference");
318             }
319              
320 5 50       14 if (@_ % 2) {
321 0         0 warnings::warnif('misc', 'Odd number of elements in pairfirst');
322             }
323              
324 5         11 my $pkg = caller;
325 24     24   152 no strict 'refs';
  24         53  
  24         28531  
326 5         8 my $glob_a = \*{"${pkg}::a"};
  5         17  
327 5         7 my $glob_b = \*{"${pkg}::b"};
  5         12  
328              
329 5         30 foreach my $i (map $_*2, 0 .. int($#_/2)) {
330 13         50 local (*$glob_a, *$glob_b) = \( @_[$i,$i+1] );
331 13 100       25 return wantarray ? @_[$i,$i+1] : 1
    100          
332             if $f->();
333             }
334 2         15 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         15  
340              
341             sub uniq (@) {
342 5     5 1 3771 my %seen;
343             my $undef;
344 5 100       55 my @uniq = grep defined($_) ? !$seen{$_}++ : !$undef++, @_;
345 5         237 @uniq;
346             }
347              
348             sub uniqnum (@) {
349 838     838 1 5190697 my %seen;
350             my $sv;
351 838         11748 require B;
352 838         6783 my $b = B::svref_2object(\$sv);
353             my @uniq =
354             grep {
355 333453         396763 my $nv = $_;
356 333453         344955 my $k;
357 333453 50 66     491961 if (ref $nv && defined &overload::ov_method && defined &overload::mycan) {
      66        
358 3         6 my $package = ref $nv;
359             # also covers Math::BigInt and Math::BigFloat
360 3 50 33     22 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         95 $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       733097 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         35202 $k = '0';
384             }
385             elsif ($nv*0 != $nv*0) {
386 309         464 $k = sprintf '%f', $nv;
387             }
388             elsif (int($nv) != $nv) {
389 93167         131883 $k = 'N' . pack('F', $nv);
390             }
391             else {
392 210189         226901 $sv = $nv + 0;
393 210189         284378 my $flags = $b->FLAGS;
394 210189 100       313719 if ($flags & B::SVf_IVisUV()) {
    100          
    50          
395 774         1543 $k = sprintf '%u', $nv;
396             }
397             elsif ($flags & B::SVf_IOK()) {
398 192796         301790 $k = sprintf '%d', $nv;
399             }
400             elsif ($flags & B::SVf_NOK()) {
401 16619         128531 $k = sprintf '%.0f', $nv;
402             }
403             else {
404 0         0 $k = $nv;
405             }
406             }
407 333453         649703 !$seen{$k}++;
408             }
409             map +(defined($_) ? $_
410 838 100       135037 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2         363  
  2         16  
411             @_;
412 838         37684 @uniq;
413             }
414              
415             sub uniqint (@) {
416 9     9 1 1888 my %seen;
417             my @uniq =
418             map +(
419             ref $_ ? $_ : int($_)
420             ),
421             grep {
422             !$seen{
423 18 50       141 /\A[0-9]+\z/ ? $_
    100          
424             : $_ > 0 ? sprintf '%u', $_
425             : sprintf '%d', $_
426             }++;
427             }
428             map +(defined($_) ? $_
429 9 100       34 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2 100       222  
  2         14  
430             @_;
431 9         57 @uniq;
432             }
433              
434             sub uniqstr (@) {
435 13     13 1 2133 my %seen;
436             my @uniq =
437             grep !$seen{$_}++,
438             map +(defined($_) ? $_
439 13 100       116 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); '' }),
  2         362  
  2         19  
440             @_;
441 13         84 @uniq;
442             }
443              
444             sub head ($@) {
445 11     11 1 9520 my $size = shift;
446             return @_
447 11 100       59 if $size > @_;
448 8 100       37 @_[ 0 .. ( $size >= 0 ? $size - 1 : $#_ + $size ) ];
449             }
450              
451             sub tail ($@) {
452 9     9 1 7253 my $size = shift;
453             return @_
454 9 100       27 if $size > @_;
455 8 100       33 @_[ ( $size >= 0 ? ($#_ - ($size-1) ) : 0 - $size ) .. $#_ ];
456             }
457              
458             sub zip_longest {
459             map {
460 6   100 6 1 127 my $idx = $_;
  8         10  
461 8         37 [ 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 104 my $idx = $_;
  8         10  
477 8         28 map $_->[$idx], @_;
478             } ( 0 .. max(map $#$_, @_) || -1 )
479             }
480              
481             sub mesh_shortest {
482             map {
483 1   50 1 1 6 my $idx = $_;
  2         3  
484 2         8 map $_->[$idx], @_;
485             } ( 0 .. min(map $#$_, @_) || -1 )
486             }
487              
488             *mesh = \&mesh_longest;
489              
490             1;
491              
492             __END__