File Coverage

blib/lib/List/Util/PP.pm
Criterion Covered Total %
statement 239 263 90.8
branch 84 108 77.7
condition 47 75 62.6
subroutine 47 47 100.0
pod 33 33 100.0
total 450 526 85.5


line stmt bran cond sub pod time code
1             package List::Util::PP;
2 24     24   955815 use strict;
  24         213  
  24         546  
3 24     24   94 use warnings;
  24         31  
  24         461  
4 24     24   85 use Exporter ();
  24         46  
  24         1704  
5              
6             our $VERSION = '1.500010';
7             $VERSION =~ tr/_//d;
8              
9             our @EXPORT_OK;
10             BEGIN {
11 24     24   1719 @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   206 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   120 no strict 'refs';
  24         58  
  24         4330  
36 25         34 ${"${pkg}::a"} = ${"${pkg}::a"};
  25         72  
  25         107  
37 25         33 ${"${pkg}::b"} = ${"${pkg}::b"};
  25         47  
  25         63  
38              
39             # May be imported by List::Util if very old version is installed, which
40             # expects default exports
41 25 50 33     106 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         14027 goto &Exporter::import;
48             }
49              
50             sub reduce (&@) {
51 32     32 1 11516 my $f = shift;
52 32 100 100     77 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  28         56  
  25         68  
53 7         33 require Carp;
54 7         533 Carp::croak("Not a subroutine reference");
55             }
56              
57 25 100       46 return shift unless @_ > 1;
58              
59 23         32 my $pkg = caller;
60 23         27 my $a = shift;
61              
62 24     24   137 no strict 'refs';
  24         35  
  24         4064  
63 23         25 local *{"${pkg}::a"} = \$a;
  23         57  
64 23         28 my $glob_b = \*{"${pkg}::b"};
  23         35  
65              
66 23         37 foreach my $b (@_) {
67 92         243 local *$glob_b = \$b;
68 92         113 $a = $f->();
69             }
70              
71 21         102 $a;
72             }
73              
74             sub reductions (&@) {
75 5     5 1 961 my $f = shift;
76 5 50 33     13 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         9  
  5         13  
77 0         0 require Carp;
78 0         0 Carp::croak("Not a subroutine reference");
79             }
80              
81 5 100       12 return unless @_;
82 4 50       10 return shift unless @_ > 1;
83              
84 4         6 my $pkg = caller;
85 4         5 my $a = shift;
86              
87 24     24   139 no strict 'refs';
  24         49  
  24         25684  
88 4         4 local *{"${pkg}::a"} = \$a;
  4         13  
89 4         5 my $glob_b = \*{"${pkg}::b"};
  4         6  
90              
91 4         9 my @o = $a;
92              
93 4         6 foreach my $b (@_) {
94 13         14 local *$glob_b = \$b;
95 13         16 $a = $f->();
96 12         32 push @o, $a;
97             }
98              
99 3         8 @o;
100             }
101              
102             sub first (&@) {
103 23     23 1 7471 my $f = shift;
104 23 100 100     57 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  20         39  
  18         50  
105 5         21 require Carp;
106 5         406 Carp::croak("Not a subroutine reference");
107             }
108              
109             $f->() and return $_
110 18   100     41 foreach @_;
111              
112 5         30 undef;
113             }
114              
115             sub sum (@) {
116 22 100   22 1 17898 return undef unless @_;
117 21         30 my $s = 0;
118 21         97 $s += $_ foreach @_;
119 21         604 return $s;
120             }
121              
122             sub min (@) {
123 16 50   16 1 12082 return undef unless @_;
124 16         43 my $min = shift;
125             $_ < $min and $min = $_
126 16   66     85 foreach @_;
127 16         315 return $min;
128             }
129              
130             sub max (@) {
131 21 100   21 1 5266 return undef unless @_;
132 19         27 my $max = shift;
133             $_ > $max and $max = $_
134 19   66     78 foreach @_;
135 19         436 return $max;
136             }
137              
138             sub minstr (@) {
139 4 50   4 1 1886 return undef unless @_;
140 4         8 my $min = shift;
141             $_ lt $min and $min = $_
142 4   66     19 foreach @_;
143 4         7 return $min;
144             }
145              
146             sub maxstr (@) {
147 4 50   4 1 1810 return undef unless @_;
148 4         5 my $max = shift;
149             $_ gt $max and $max = $_
150 4   66     20 foreach @_;
151 4         6 return $max;
152             }
153              
154             sub shuffle (@) {
155 6     6 1 3011 sample(scalar @_, @_);
156             }
157              
158             sub sample ($@) {
159 16     16 1 3500 my $num = shift;
160 16         37 my @i = (0 .. $#_);
161 16 100       33 $num = @_ if $num > @_;
162 16 100       148 my @o = defined $RAND ? (map +(splice @i, $RAND->($#i), 1), 1 .. $num)
163             : (map +(splice @i, rand($#i), 1), 1 .. $num);
164 16         110 @_[@o];
165             }
166              
167             sub all (&@) {
168 4     4 1 533 my $f = shift;
169 4 50 33     14 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         6  
  4         15  
170 0         0 require Carp;
171 0         0 Carp::croak("Not a subroutine reference");
172             }
173              
174             $f->() or return !!0
175 4   100     8 foreach @_;
176 3         25 return !!1;
177             }
178              
179             sub any (&@) {
180 5     5 1 1068 my $f = shift;
181 5 50 33     20 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         8  
  5         21  
182 0         0 require Carp;
183 0         0 Carp::croak("Not a subroutine reference");
184             }
185              
186             $f->() and return !!1
187 5   100     13 foreach @_;
188 2         12 return !!0;
189             }
190              
191             sub none (&@) {
192 4     4 1 718 my $f = shift;
193 4 50 33     23 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     9 foreach @_;
200 2         12 return !!1;
201             }
202              
203             sub notall (&@) {
204 4     4 1 381 my $f = shift;
205 4 50 33     12 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  4         6  
  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     10 foreach @_;
212 3         21 return !!0;
213             }
214              
215             sub product (@) {
216 25     25 1 10133 my $p = 1;
217 25         103 $p *= $_ foreach @_;
218 25         650 return $p;
219             }
220              
221             sub sum0 (@) {
222 3     3 1 1003 my $s = 0;
223 3         6 $s += $_ foreach @_;
224 3         6 return $s;
225             }
226              
227             sub pairs (@) {
228 3 100   3 1 12960 if (@_ % 2) {
229 1         67 warnings::warnif('misc', 'Odd number of elements in pairs');
230             }
231              
232             return
233 3         14 map { bless [ @_[$_, $_ + 1] ], 'List::Util::PP::_Pair' }
  7         31  
234             map $_*2,
235             0 .. int($#_/2);
236             }
237              
238             sub unpairs (@) {
239 3     3 1 373 map @{$_}[0,1], @_;
  7         22  
240             }
241              
242             sub pairkeys (@) {
243 1 50   1 1 4 if (@_ % 2) {
244 0         0 warnings::warnif('misc', 'Odd number of elements in pairkeys');
245             }
246              
247             return
248 1         9 map $_[$_*2],
249             0 .. int($#_/2);
250             }
251              
252             sub pairvalues (@) {
253 1 50   1 1 4 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         9 map $_[$_*2 + 1],
260             0 .. int($#_/2);
261             }
262              
263             sub pairmap (&@) {
264 11     11 1 2843 my $f = shift;
265 11 50 33     30 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  11         17  
  11         35  
266 0         0 require Carp;
267 0         0 Carp::croak("Not a subroutine reference");
268             }
269              
270 11 100       23 if (@_ % 2) {
271 1         67 warnings::warnif('misc', 'Odd number of elements in pairmap');
272             }
273              
274 11         17 my $pkg = caller;
275 24     24   177 no strict 'refs';
  24         37  
  24         4207  
276 11         12 my $glob_a = \*{"${pkg}::a"};
  11         32  
277 11         22 my $glob_b = \*{"${pkg}::b"};
  11         14  
278              
279             return
280             map {
281 11         44 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  30         314  
282 30         46 $f->();
283             }
284             map $_*2,
285             0 .. int($#_/2);
286             }
287              
288             sub pairgrep (&@) {
289 7     7 1 928 my $f = shift;
290 7 50 33     19 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  7         10  
  7         22  
291 0         0 require Carp;
292 0         0 Carp::croak("Not a subroutine reference");
293             }
294              
295 7 100       17 if (@_ % 2) {
296 2         210 warnings::warnif('misc', 'Odd number of elements in pairgrep');
297             }
298              
299 7         69 my $pkg = caller;
300 24     24   144 no strict 'refs';
  24         41  
  24         4393  
301 7         8 my $glob_a = \*{"${pkg}::a"};
  7         21  
302 7         9 my $glob_b = \*{"${pkg}::b"};
  7         11  
303              
304             return
305             map {
306 7         28 local (*$glob_a, *$glob_b) = \( @_[$_,$_+1] );
  18         60  
307 18 100       30 $f->() ? (wantarray ? @_[$_,$_+1] : 1) : ();
    100          
308             }
309             map $_*2,
310             0 .. int ($#_/2);
311             }
312              
313             sub pairfirst (&@) {
314 5     5 1 831 my $f = shift;
315 5 50 33     17 unless ( length ref $f && eval { $f = \&$f; 1 } ) {
  5         9  
  5         16  
316 0         0 require Carp;
317 0         0 Carp::croak("Not a subroutine reference");
318             }
319              
320 5 50       13 if (@_ % 2) {
321 0         0 warnings::warnif('misc', 'Odd number of elements in pairfirst');
322             }
323              
324 5         9 my $pkg = caller;
325 24     24   138 no strict 'refs';
  24         48  
  24         23641  
326 5         6 my $glob_a = \*{"${pkg}::a"};
  5         12  
327 5         6 my $glob_b = \*{"${pkg}::b"};
  5         8  
328              
329 5         23 foreach my $i (map $_*2, 0 .. int($#_/2)) {
330 13         41 local (*$glob_a, *$glob_b) = \( @_[$i,$i+1] );
331 13 100       18 return wantarray ? @_[$i,$i+1] : 1
    100          
332             if $f->();
333             }
334 2         11 return ();
335             }
336              
337 1     1   7 sub List::Util::PP::_Pair::key { $_[0][0] }
338 1     1   3 sub List::Util::PP::_Pair::value { $_[0][1] }
339 2     2   3 sub List::Util::PP::_Pair::TO_JSON { [ @{$_[0]} ] }
  2         13  
340              
341             sub uniq (@) {
342 5     5 1 3598 my %seen;
343             my $undef;
344 5 100       54 my @uniq = grep defined($_) ? !$seen{$_}++ : !$undef++, @_;
345 5         197 @uniq;
346             }
347              
348             sub uniqnum (@) {
349 838     838 1 4501319 my %seen;
350             my @uniq =
351             grep {
352 333453         373441 my $nv = $_;
353 333453 50 66     415579 if (ref $nv && defined &overload::ov_method && defined &overload::mycan) {
      66        
354 3         5 my $package = ref $nv;
355 3 50 33     16 if (UNIVERSAL::isa($nv, 'Math::BigInt')) {
    50          
    0          
356 0         0 $nv = \($nv->bstr);
357             }
358             elsif(my $method
359             = overload::ov_method(overload::mycan($package, '(0+'), $package)
360             || overload::ov_method(overload::mycan($package, '""'), $package)
361             || overload::ov_method(overload::mycan($package, 'bool'), $package)
362             ) {
363 3         2198 $nv = $nv->$method(undef, !!0);
364             }
365             elsif (
366             my $nomethod = overload::ov_method(overload::mycan($package, '(nomethod'), $package)
367             ) {
368 0         0 $nv = $nv->$nomethod(undef, undef, '0+');
369             }
370             }
371 333453 50       358886 if (ref $nv) {
372 0         0 $nv = \('R' . 0+$nv);
373             }
374 333453         291319 my $iv = $nv;
375 333453         438876 my $F;
376             my $NV;
377 333453         0 my $f;
378              
379             !$seen{
380 333453 100 100     1444526 ref $nv ? $$nv
    100          
    100          
    100          
    100          
    100          
    50          
381             : ($NV = (unpack 'F', ($F = pack 'F', $nv))[0]) == 0
382             ? 0
383             : $NV != $NV ? sprintf('%f', $NV)
384             : int($NV) != $NV ? 'N'.$F
385             : (
386             $iv - 1 == $iv
387             ) ? sprintf('%.0f', $NV)
388             : (
389             ($f = sprintf('%.0f', $NV)) ne sprintf('%.0f', $NV + 1)
390             &&
391             ($f) ne sprintf('%.0f', $NV - 1)
392             ) ? $f
393             : $NV > 0 ? sprintf('%u', $iv)
394             : sprintf('%d', $iv)
395             }++;
396             }
397             map +(defined($_) ? $_
398 838 100       97673 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2         308  
  2         15  
399             @_;
400 838         25123 @uniq;
401             }
402              
403             sub uniqint (@) {
404 9     9 1 1667 my %seen;
405             my @uniq =
406             map +(
407             ref $_ ? $_ : int($_)
408             ),
409             grep {
410             !$seen{
411 18 50       123 /\A[0-9]+\z/ ? $_
    100          
412             : $_ > 0 ? sprintf '%u', $_
413             : sprintf '%d', $_
414             }++;
415             }
416             map +(defined($_) ? $_
417 9 100       27 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); 0 }),
  2 100       180  
  2         13  
418             @_;
419 9         49 @uniq;
420             }
421              
422             sub uniqstr (@) {
423 13     13 1 1868 my %seen;
424             my @uniq =
425             grep !$seen{$_}++,
426             map +(defined($_) ? $_
427 13 100       95 : do { warnings::warnif('uninitialized', 'Use of uninitialized value in subroutine entry'); '' }),
  2         269  
  2         16  
428             @_;
429 13         68 @uniq;
430             }
431              
432             sub head ($@) {
433 11     11 1 8333 my $size = shift;
434             return @_
435 11 100       26 if $size > @_;
436 8 100       29 @_[ 0 .. ( $size >= 0 ? $size - 1 : $#_ + $size ) ];
437             }
438              
439             sub tail ($@) {
440 9     9 1 6527 my $size = shift;
441             return @_
442 9 100       22 if $size > @_;
443 8 100       31 @_[ ( $size >= 0 ? ($#_ - ($size-1) ) : 0 - $size ) .. $#_ ];
444             }
445              
446             sub zip_longest {
447             map {
448 6   100 6 1 89 my $idx = $_;
  8         9  
449 8         27 [ map $_->[$idx], @_ ];
450             } ( 0 .. max(map $#$_, @_) || -1 )
451             }
452              
453             sub zip_shortest {
454             map {
455 1   50 1 1 5 my $idx = $_;
  2         3  
456 2         8 [ map $_->[$idx], @_ ];
457             } ( 0 .. min(map $#$_, @_) || -1 )
458             }
459              
460             *zip = \&zip_longest;
461              
462             sub mesh_longest {
463             map {
464 6   100 6 1 98 my $idx = $_;
  8         10  
465 8         25 map $_->[$idx], @_;
466             } ( 0 .. max(map $#$_, @_) || -1 )
467             }
468              
469             sub mesh_shortest {
470             map {
471 1   50 1 1 7 my $idx = $_;
  2         3  
472 2         9 map $_->[$idx], @_;
473             } ( 0 .. min(map $#$_, @_) || -1 )
474             }
475              
476             *mesh = \&mesh_longest;
477              
478             1;
479              
480             __END__