File Coverage

blib/lib/Perlude.pm
Criterion Covered Total %
statement 125 145 86.2
branch 50 60 83.3
condition 6 12 50.0
subroutine 38 48 79.1
pod 18 19 94.7
total 237 284 83.4


line stmt bran cond sub pod time code
1             package Perlude;
2 14     14   166074 use Perlude::Open;
  14         26  
  14         692  
3 14     14   63 use strict;
  14         17  
  14         289  
4 14     14   46 use warnings;
  14         14  
  14         237  
5 14     14   96 use 5.10.0;
  14         28  
  14         386  
6 14     14   52 use Carp qw< croak >;
  14         18  
  14         821  
7 14     14   57 use Exporter qw< import >;
  14         18  
  14         874  
8             our @EXPORT = qw<
9             fold unfold
10             takeWhile take drop
11             filter apply
12             now
13             cycle range
14             tuple
15             concat concatC concatM
16             records lines
17             pairs
18             nth
19             chunksOf
20             open_file
21             >;
22              
23             # ABSTRACT: Shell and Powershell pipes, haskell keywords mixed with the awesomeness of perl. forget shell scrpting now!
24              
25 14     14   52 use Carp;
  14         15  
  14         16739  
26              
27             our $VERSION = '0.61';
28              
29             sub pairs ($) {
30 2     2 1 752 my ( $ref ) = @_;
31 2 100       17 my $isa = ref $ref or die "'$ref' isn't a ref";
32              
33             # TODO: use reftypes here!
34 1 50       5 if ($isa eq 'HASH') {
35             sub {
36 6     6   4 my @pair;
37 6         21 while ( @pair = each %$ref ) { return \@pair }
  5         18  
38             ()
39 1         3 }
40 1         7 }
41             # elsif ($isa eq 'ARRAY') {
42             # my $index = 1;
43             # sub {
44             # return if $index > @$ref;
45             # my $r =
46             # [ $$ref[$index-1]
47             # , $$ref[$index] ];
48             # $index+=2;
49             # $r;
50             # }
51             # }
52 0         0 else { die "can't pair this kind of ref: $isa" }
53             }
54              
55             # sub pairs (&$) {
56             # my ( $do, $on ) = @_;
57             # sub {
58             # while ( @$_ = each %$on ) { return $do->() }
59             # ()
60             # }
61             # }
62              
63             # private helpers
64             sub _buffer ($) {
65 90     90   71 my ($i) = @_;
66 90         64 my @b;
67             sub {
68 50281 100   50281   51854 return shift @b if @b;
69 50280         44167 @b = ( $i->() );
70 50280 100       164538 return @b ? shift @b : ();
71             }
72 90         247 }
73              
74             # interface with the Perl world
75             sub unfold (@) {
76 41     41 1 15574 my @array = @_;
77 159 100   159   367 sub { @array ? shift @array : () }
78 41         1011 }
79              
80             sub fold ($) {
81 96     96 1 3207 my ( $i ) = @_;
82 96         84 my @v;
83 96 100       207 unless (wantarray) {
84 23 100       40 if (defined wantarray) {
85 6         8 my $n = 0;
86 6         15 $n += @v while @v = $i->();
87 6         26 return $n;
88             } else {
89 17         30 undef while @v = $i->();
90 17         95 return;
91             }
92             }
93 73         58 my @r;
94 73         122 push @r, @v while @v = $i->();
95 73         2515 @r;
96             }
97              
98             # stream consumers (lazy)
99             sub takeWhile (&$) {
100 4     4 1 1442 my ($cond, $i ) = @_;
101             sub {
102 7 100   7   30 ( my @v = $i->() ) or return;
103 6 100       16 return $cond->() ? @v : () for @v;
104             }
105 4         24 }
106              
107             sub filter (&$) {
108 3     3 1 623 my ( $cond, $i ) = @_;
109 3         7 $i = _buffer $i;
110             sub {
111 10006     10006   5135 while (1) {
112 20009 100       34230 ( my @v = $i->() ) or return;
113 20007   100     24554 $cond->() and return @v for @v;
114             }
115             }
116 3         20 }
117              
118             sub take ($$) {
119 72     72 1 3771 my ( $n, $i ) = @_;
120 72         90 $i = _buffer $i;
121             sub {
122 30212 100   30212   35927 $n-- > 0 or return;
123 30179         22717 $i->()
124             }
125 72         185 }
126              
127             sub drop ($$) {
128 12     12 1 6914 my ( $n, $i ) = @_;
129 12         20 $i = _buffer $i;
130 12         21 fold take $n, $i;
131 12         48 $i;
132             }
133              
134             sub apply (&$) {
135 3     3 1 44397 my ( $code, $i ) = @_;
136             sub {
137 10007 100   10007   9289 ( my @v = $i->() ) or return;
138 10006         29711 (map $code->(), @v)[0];
139             }
140 3         17 }
141              
142             # stream consumers (exhaustive)
143             sub now (&$) {
144 5     5 1 1305 my ( $code, $i ) = @_;
145 5         7 my @b;
146 5         7 while (1) {
147 32 100       1407 ( my @v = $i->() ) or return pop @b;
148 27         40 @b = map $code->(), @v;
149             }
150             }
151              
152             sub records {
153 0     0 1 0 my $source = shift;
154 0   0 0   0 sub { <$source> // () }
155 0         0 }
156              
157              
158             sub lines {
159 3     3 1 2010 my $fh = &open_file;
160 3         5 my $line;
161             sub {
162 12 100   12   56 return unless defined ( $line = <$fh> );
163 9         13 chomp $line;
164 9         36 $line;
165             }
166 3         20 }
167              
168             sub concat {
169 1     1 1 2 my ($s, @ss) = @_; # streams
170 1         1 my @v;
171             sub {
172 11     11   6 while (1) {
173 12 100       10 @v = $s->() and return @v;
174 2 100       6 $s = shift @ss or return ();
175             }
176             }
177 1         5 }
178              
179             sub concatC ($) {
180 0     0 1 0 my $ss = shift; # stream
181 0 0   0   0 my ($s) = $ss->() or return sub {()};
  0         0  
182 0         0 my @v;
183             sub {
184 0     0   0 while (1) {
185 0 0       0 @v = $s->() and return @v;
186 0 0       0 $s = $ss->() or return ();
187             }
188             }
189 0         0 }
190              
191             sub concatM (&$) {
192 0     0 1 0 my ( $apply, $stream ) = @_;
193 0     0   0 concatC apply {$apply->()} $stream;
  0         0  
194             }
195              
196             # stream generators
197             sub cycle (@) {
198 0 50   0 1 0 (my @ring = @_) or return sub {};
  2     2   9  
199 2         4 my $index = -1;
200 10010     10010   10094 sub { $ring[ ( $index += 1 ) %= @ring ] }
201 2         12 }
202              
203             sub range {
204 14   33 14 1 40 my $begin = shift // croak "range begin undefined";
205 14         13 my $end = shift;
206 14   100     26 my $step = shift // 1;
207              
208 14 50   0   24 return sub { () } if $step == 0;
  0         0  
209              
210 14         10 $begin -= $step;
211 14 100       22 if (defined $end) {
212 9 100       11 if ($step > 0) {
213 22 100   22   61 sub { (($begin += $step) <= $end) ? ($begin) : () }
214 6         29 } else {
215 8 100   8   20 sub { (($begin += $step) >= $end) ? ($begin) : () }
216 3         13 }
217             } else {
218 15     15   16 sub { ($begin += $step) }
219 5         22 }
220             }
221              
222              
223             sub tuple ($$) {
224 6     6 0 3015 my ( $n, $i ) = @_;
225 6 100       381 croak "$n is not a valid parameter for tuple()" if $n <= 0;
226 3         6 $i = _buffer $i;
227             sub {
228 9     9   12 my @v = fold take $n, $i;
229 9 100       40 @v ? \@v : ();
230             }
231 3         21 }
232              
233             sub nth {
234 0     0 1 0 my ( $n, $s ) = @_;
235 0         0 $n--;
236 0         0 take 1, drop $n, $s
237             }
238              
239             sub chunksOf ($$;$) {
240              
241 1     1 1 13 my ( $n, $src, $offset ) = @_;
242 1 50       4 $n > 1 or die "chunksOf must be at least 1 (don't forget unfold)";
243 1   50     6 $offset //= 0;
244              
245 1         2 my ( $end , $exhausted , $from, $to )
246             = ( $#$src , 0 );
247              
248             sub {
249 4 100   4   14 return if $exhausted;
250              
251 2         4 ( $from , $offset )=
252             ( $offset , $offset + $n );
253              
254 2 100       6 $end <= ($to = $offset - 1) and do {
255 1         2 $exhausted=1;
256 1         1 $to = $end;
257             };
258              
259 2         4 [ @{$src}[$from..$to] ];
  2         12  
260             }
261 1         8 }
262              
263              
264             1;
265