File Coverage

blib/lib/Lazy/Util.pm
Criterion Covered Total %
statement 127 128 99.2
branch 31 32 96.8
condition 5 9 55.5
subroutine 31 31 100.0
pod 15 15 100.0
total 209 215 97.2


line stmt bran cond sub pod time code
1 1     1   14146 use strict;
  1         2  
  1         24  
2 1     1   4 use warnings;
  1         2  
  1         40  
3              
4             package Lazy::Util;
5             $Lazy::Util::VERSION = '0.002';
6             #ABSTRACT: Perl utilities for lazy evaluation
7              
8              
9 1     1   4 use Carp qw/ croak /;
  1         2  
  1         63  
10 1     1   9 use Exporter qw/ import /;
  1         2  
  1         39  
11 1     1   289 use Lazy::Util::OO;
  1         2  
  1         23  
12 1     1   4 use Scalar::Util qw/ blessed /;
  1         2  
  1         40  
13              
14 1     1   5 use constant SCALAR_DEFER => eval { require Scalar::Defer; 1 };
  1         2  
  1         1  
  1         1564  
  0         0  
15              
16             our @EXPORT_OK = qw/
17             l_concat l_first l_grep l_map l_nuniq l_uniq l_until g_count g_first g_join
18             g_last g_max g_min g_prod g_sum
19             /;
20              
21             our %EXPORT_TAGS = (all => [@EXPORT_OK],);
22              
23 86 100   86   413 sub _isa { defined blessed $_[0] and $_[0]->isa($_[1]); }
24              
25              
26             sub l_concat {
27 28     28 1 97 my (@vals) = grep defined, @_;
28              
29 28 100   8   110 return Lazy::Util::OO->new(sub {undef}) if @vals == 0;
  8         17  
30              
31 20 50 66     55 return $vals[0] if @vals == 1 and _isa($vals[0], 'Lazy::Util::OO');
32              
33             return Lazy::Util::OO->new(
34             sub {
35 98     98   224 while (@vals) {
36              
37             # if it's a Scalar::Defer or a CODE reference, coerce into a
38             # Lazy::Util::OO object
39 84 100 33     448 $vals[0] = Lazy::Util::OO->new($vals[0])
      66        
40             if SCALAR_DEFER && _isa($vals[0], 0)
41             or ref $vals[0] eq 'CODE';
42              
43             # if by this point it's not a Lazy::Util::OO object, simply return it
44             # and remove from @vals
45 84 100       160 return shift @vals if not _isa($vals[0], 'Lazy::Util::OO');
46              
47             # ->get the next value from the Lazy::Util::OO object and return it if
48             # it's defined
49 4 100       12 if (defined(my $get = $vals[0]->get())) { return $get; }
  3         7  
50 1         6 else { shift @vals; }
51             }
52 15         34 return undef;
53             }
54 20         143 );
55             }
56              
57              
58             sub l_first {
59 1     1 1 4 my ($n, @vals) = @_;
60              
61 1         3 my $vals = l_concat @vals;
62              
63             return Lazy::Util::OO->new(
64             sub {
65 4 100   4   16 return $vals->get() if $n-- > 0;
66 1         2 return undef;
67             }
68 1         5 );
69             }
70              
71              
72             sub l_grep (&@) {
73 1     1 1 4 my ($grep, @vals) = @_;
74              
75 1         4 my $vals = l_concat @vals;
76              
77             return Lazy::Util::OO->new(
78             sub {
79 3     3   9 while (defined(my $get = $vals->get())) {
80 5         11 for ($get) {
81 5 100       9 if ($grep->($get)) { return $get }
  2         11  
82             }
83             }
84              
85 1         2 return undef;
86             }
87 1         6 );
88             }
89              
90              
91             sub l_map (&@) {
92 2     2 1 9 my ($map, @vals) = @_;
93              
94 2         6 my $vals = l_concat @vals;
95              
96 2         4 my @subvals = ();
97             return Lazy::Util::OO->new(
98             sub {
99 8 100   8   23 return shift @subvals if @subvals;
100              
101 7         20 while (not @subvals) {
102 10         33 my $get = $vals->get();
103 10 100       25 return undef if not defined $get;
104              
105 8         19 @subvals = $map->($get) for $get;
106             }
107              
108 5         34 return shift @subvals;
109             }
110 2         11 );
111             }
112              
113              
114             sub l_nuniq {
115 1     1 1 4 my (@vals) = @_;
116              
117 1         3 my $vals = l_concat @vals;
118              
119 1         2 my %uniq;
120             return Lazy::Util::OO->new(
121             sub {
122 5     5   14 while (defined(my $get = $vals->get())) {
123 9         15 my $key = 0 + $get;
124 9 100       38 $uniq{$key}++ or return $get;
125             }
126 1         3 return undef;
127             }
128 1         5 );
129             }
130              
131              
132             sub l_uniq {
133 1     1 1 7 my (@vals) = @_;
134              
135 1         6 my $vals = l_concat @vals;
136              
137 1         2 my %uniq;
138             return Lazy::Util::OO->new(
139             sub {
140 5     5   15 while (defined(my $get = $vals->get())) {
141 9 100       32 $uniq{$get}++ or return $get;
142             }
143 1         5 return undef;
144             }
145 1         6 );
146             }
147              
148              
149             sub l_until (&@) {
150 2     2 1 10 my ($until, @vals) = @_;
151              
152 2         6 my $vals = l_concat @vals;
153              
154 2         4 my $found = 0;
155             return Lazy::Util::OO->new(
156             sub {
157 9 100   9   23 return undef if $found;
158              
159 7         19 my $get = $vals->get();
160 7         21 $found = $until->($get) for $get;
161              
162 7         29 return $get;
163             }
164 2         9 );
165             }
166              
167              
168             sub g_count {
169 2     2 1 6 my (@vals) = @_;
170              
171 2         6 my $vals = l_concat @vals;
172              
173 2         6 my $n = 0;
174 2         6 while (defined $vals->get()) { $n++; }
  4         9  
175              
176 2         22 return $n;
177             }
178              
179              
180             sub g_first {
181 2     2 1 6 my (@vals) = @_;
182              
183 2         6 my $vals = l_concat @vals;
184              
185 2         7 return $vals->get();
186             }
187              
188              
189             sub g_join {
190 3     3 1 9 my ($sep, @vals) = @_;
191              
192 3         8 my $vals = l_concat @vals;
193              
194 3         9 my $ret = $vals->get();
195 3         7 while (defined(my $get = $vals->get())) { $ret .= $sep . $get; }
  2         6  
196              
197 3         20 return $ret;
198             }
199              
200              
201             sub g_last {
202 2     2 1 5 my @vals = @_;
203              
204 2         5 my $vals = l_concat @vals;
205              
206 2         4 my $ret = undef;
207 2         5 while (defined(my $get = $vals->get())) { $ret = $get; }
  3         8  
208              
209 2         13 return $ret;
210             }
211              
212              
213             sub g_max {
214 2     2 1 18 my @vals = @_;
215              
216 2         11 my $vals = l_concat @vals;
217              
218 2         7 my $ret = $vals->get();
219 2 100       6 while (defined(my $get = $vals->get())) { $ret = $get if $get > $ret; }
  6         19  
220              
221 2         13 return $ret;
222             }
223              
224              
225             sub g_min {
226 2     2 1 8 my @vals = @_;
227              
228 2         5 my $vals = l_concat @vals;
229              
230 2         6 my $ret = $vals->get();
231 2 100       5 while (defined(my $get = $vals->get())) { $ret = $get if $get < $ret; }
  7         19  
232              
233 2         13 return $ret;
234             }
235              
236              
237             sub g_prod {
238 3     3 1 9 my @vals = @_;
239              
240 3         10 my $vals = l_concat @vals;
241              
242 3         6 my $ret = 1;
243 3         7 while (defined(my $get = $vals->get())) {
244 7         11 $ret *= $get;
245 7 100       25 return 0 if $ret == 0;
246             }
247              
248 2         11 return $ret;
249             }
250              
251              
252             sub g_sum {
253 2     2 1 6 my @vals = @_;
254              
255 2         5 my $vals = l_concat @vals;
256              
257 2         4 my $ret = 0;
258 2         7 while (defined(my $get = $vals->get())) { $ret += $get; }
  3         8  
259              
260 2         12 return $ret;
261             }
262              
263             1;
264              
265             __END__