File Coverage

blib/lib/Perlude.pm
Criterion Covered Total %
statement 125 145 86.2
branch 49 60 81.6
condition 6 12 50.0
subroutine 38 48 79.1
pod 18 19 94.7
total 236 284 83.1


line stmt bran cond sub pod time code
1             package Perlude;
2 13     13   365018 use Perlude::Open;
  13         36  
  13         635  
3 13     13   67 use strict;
  13         23  
  13         318  
4 13     13   84 use warnings;
  13         18  
  13         262  
5 13     13   124 use 5.10.0;
  13         40  
  13         477  
6 13     13   66 use Carp qw< croak >;
  13         28  
  13         764  
7 13     13   67 use Exporter qw< import >;
  13         21  
  13         793  
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 13     13   58 use Carp;
  13         18  
  13         21922  
26              
27             our $VERSION = '0.58';
28              
29             sub pairs ($) {
30 2     2 1 884 my ( $ref ) = @_;
31 2 100       19 my $isa = ref $ref or die "'$ref' isn't a ref";
32              
33             # TODO: use reftypes here!
34 1 50       4 if ($isa eq 'HASH') {
35             sub {
36 6     6   7 my @pair;
37 6         18 while ( @pair = each %$ref ) { return \@pair }
  5         19  
38             ()
39 1         4 }
40 1         9 }
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 88     88   108 my ($i) = @_;
66 88         96 my @b;
67             sub {
68 50275 50   50275   83574 return shift @b if @b;
69 50275         72689 @b = ( $i->() );
70 50275 100       265181 return @b ? shift @b : ();
71             }
72 88         344 }
73              
74             # interface with the Perl world
75             sub unfold (@) {
76 41     41 1 18872 my @array = @_;
77 159 100   159   474 sub { @array ? shift @array : () }
78 41         1893 }
79              
80             sub fold ($) {
81 93     93 1 2717 my ( $i ) = @_;
82 93         98 my @v;
83 93 100       220 unless (wantarray) {
84 23 100       48 if (defined wantarray) {
85 6         9 my $n = 0;
86 6         11 $n += @v while @v = $i->();
87 6         25 return $n;
88             } else {
89 17         33 undef while @v = $i->();
90 17         89 return;
91             }
92             }
93 70         86 my @r;
94 70         162 push @r, @v while @v = $i->();
95 70         4468 @r;
96             }
97              
98             # stream consumers (lazy)
99             sub takeWhile (&$) {
100 4     4 1 2638 my ($cond, $i ) = @_;
101             sub {
102 7 100   7   36 ( my @v = $i->() ) or return;
103 6 100       20 return $cond->() ? @v : () for @v;
104             }
105 4         27 }
106              
107             sub filter (&$) {
108 3     3 1 1280 my ( $cond, $i ) = @_;
109 3         9 $i = _buffer $i;
110             sub {
111 10006     10006   9070 while (1) {
112 20009 100       58222 ( my @v = $i->() ) or return;
113 20007   100     46568 $cond->() and return @v for @v;
114             }
115             }
116 3         26 }
117              
118             sub take ($$) {
119 70     70 1 5325 my ( $n, $i ) = @_;
120 70         135 $i = _buffer $i;
121             sub {
122 30204 100   30204   54497 $n-- > 0 or return;
123 30173         40184 $i->()
124             }
125 70         279 }
126              
127             sub drop ($$) {
128 12     12 1 9589 my ( $n, $i ) = @_;
129 12         26 $i = _buffer $i;
130 12         24 fold take $n, $i;
131 12         68 $i;
132             }
133              
134             sub apply (&$) {
135 2     2 1 88738 my ( $code, $i ) = @_;
136             sub {
137 10004 100   10004   17319 ( my @v = $i->() ) or return;
138 10003         47738 (map $code->(), @v)[0];
139             }
140 2         17 }
141              
142             # stream consumers (exhaustive)
143             sub now (&$) {
144 5     5 1 2445 my ( $code, $i ) = @_;
145 5         7 my @b;
146 5         8 while (1) {
147 32 100       2204 ( my @v = $i->() ) or return pop @b;
148 27         66 @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 2     2 1 1116 my $fh = &open_file;
160 2         4 my $line;
161             sub {
162 8 100   8   81 return unless defined ( $line = <$fh> );
163 6         9 chomp $line;
164 6         28 $line;
165             }
166 2         12 }
167              
168             sub concat {
169 1     1 1 3 my ($s, @ss) = @_; # streams
170 1         2 my @v;
171             sub {
172 11     11   9 while (1) {
173 12 100       17 @v = $s->() and return @v;
174 2 100       7 $s = shift @ss or return ();
175             }
176             }
177 1         6 }
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   14  
199 2         8 my $index = -1;
200 10010     10010   15685 sub { $ring[ ( $index += 1 ) %= @ring ] }
201 2         17 }
202              
203             sub range {
204 14   33 14 1 59 my $begin = shift // croak "range begin undefined";
205 14         21 my $end = shift;
206 14   100     43 my $step = shift // 1;
207              
208 14 50   0   32 return sub { () } if $step == 0;
  0         0  
209              
210 14         20 $begin -= $step;
211 14 100       28 if (defined $end) {
212 9 100       18 if ($step > 0) {
213 22 100   22   96 sub { (($begin += $step) <= $end) ? ($begin) : () }
214 6         41 } else {
215 8 100   8   33 sub { (($begin += $step) >= $end) ? ($begin) : () }
216 3         19 }
217             } else {
218 15     15   28 sub { ($begin += $step) }
219 5         29 }
220             }
221              
222              
223             sub tuple ($$) {
224 6     6 0 4981 my ( $n, $i ) = @_;
225 6 100       478 croak "$n is not a valid parameter for tuple()" if $n <= 0;
226 3         8 $i = _buffer $i;
227             sub {
228 9     9   17 my @v = fold take $n, $i;
229 9 100       77 @v ? \@v : ();
230             }
231 3         16 }
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 18 my ( $n, $src, $offset ) = @_;
242 1 50       5 $n > 1 or die "chunksOf must be at least 1 (don't forget unfold)";
243 1   50     8 $offset //= 0;
244              
245 1         5 my ( $end , $exhausted , $from, $to )
246             = ( $#$src , 0 );
247              
248             sub {
249 4 100   4   22 return if $exhausted;
250              
251 2         5 ( $from , $offset )=
252             ( $offset , $offset + $n );
253              
254 2 100       9 $end <= ($to = $offset - 1) and do {
255 1         2 $exhausted=1;
256 1         2 $to = $end;
257             };
258              
259 2         5 [ @{$src}[$from..$to] ];
  2         13  
260             }
261 1         10 }
262              
263              
264             1;
265