File Coverage

blib/lib/Perlude.pm
Criterion Covered Total %
statement 105 145 72.4
branch 41 60 68.3
condition 5 12 41.6
subroutine 34 48 70.8
pod 18 19 94.7
total 203 284 71.4


line stmt bran cond sub pod time code
1             package Perlude;
2 12     12   110853 use Perlude::Open;
  12         22  
  12         520  
3 12     12   47 use strict;
  12         13  
  12         232  
4 12     12   36 use warnings;
  12         12  
  12         190  
5 12     12   80 use 5.10.0;
  12         21  
  12         325  
6 12     12   39 use Carp qw< croak >;
  12         19  
  12         650  
7 12     12   42 use Exporter qw< import >;
  12         11  
  12         539  
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 12     12   42 use Carp;
  12         12  
  12         14638  
26              
27             our $VERSION = '0.60';
28              
29             sub pairs ($) {
30 0     0 1 0 my ( $ref ) = @_;
31 0 0       0 my $isa = ref $ref or die "'$ref' isn't a ref";
32              
33             # TODO: use reftypes here!
34 0 0       0 if ($isa eq 'HASH') {
35             sub {
36 0     0   0 my @pair;
37 0         0 while ( @pair = each %$ref ) { return \@pair }
  0         0  
38             ()
39 0         0 }
40 0         0 }
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   64 my ($i) = @_;
66 88         59 my @b;
67             sub {
68 50275 50   50275   54715 return shift @b if @b;
69 50275         44521 @b = ( $i->() );
70 50275 100       162697 return @b ? shift @b : ();
71             }
72 88         251 }
73              
74             # interface with the Perl world
75             sub unfold (@) {
76 41     41 1 11297 my @array = @_;
77 159 100   159   335 sub { @array ? shift @array : () }
78 41         1212 }
79              
80             sub fold ($) {
81 91     91 1 1461 my ( $i ) = @_;
82 91         73 my @v;
83 91 100       150 unless (wantarray) {
84 23 100       37 if (defined wantarray) {
85 6         7 my $n = 0;
86 6         10 $n += @v while @v = $i->();
87 6         19 return $n;
88             } else {
89 17         23 undef while @v = $i->();
90 17         68 return;
91             }
92             }
93 68         52 my @r;
94 68         81 push @r, @v while @v = $i->();
95 68         2537 @r;
96             }
97              
98             # stream consumers (lazy)
99             sub takeWhile (&$) {
100 4     4 1 1402 my ($cond, $i ) = @_;
101             sub {
102 7 100   7   27 ( my @v = $i->() ) or return;
103 6 100       15 return $cond->() ? @v : () for @v;
104             }
105 4         23 }
106              
107             sub filter (&$) {
108 3     3 1 655 my ( $cond, $i ) = @_;
109 3         7 $i = _buffer $i;
110             sub {
111 10006     10006   6254 while (1) {
112 20009 100       36408 ( my @v = $i->() ) or return;
113 20007   100     25836 $cond->() and return @v for @v;
114             }
115             }
116 3         19 }
117              
118             sub take ($$) {
119 70     70 1 3734 my ( $n, $i ) = @_;
120 70         87 $i = _buffer $i;
121             sub {
122 30204 100   30204   33722 $n-- > 0 or return;
123 30173         25080 $i->()
124             }
125 70         171 }
126              
127             sub drop ($$) {
128 12     12 1 5231 my ( $n, $i ) = @_;
129 12         19 $i = _buffer $i;
130 12         18 fold take $n, $i;
131 12         43 $i;
132             }
133              
134             sub apply (&$) {
135 2     2 1 48496 my ( $code, $i ) = @_;
136             sub {
137 10004 100   10004   9378 ( my @v = $i->() ) or return;
138 10003         27112 (map $code->(), @v)[0];
139             }
140 2         12 }
141              
142             # stream consumers (exhaustive)
143             sub now (&$) {
144 4     4 1 1109 my ( $code, $i ) = @_;
145 4         5 my @b;
146 4         4 while (1) {
147 29 100       64 ( my @v = $i->() ) or return pop @b;
148 25         30 @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 691 my $fh = &open_file;
160 2         2 my $line;
161             sub {
162 8 100   8   37 return unless defined ( $line = <$fh> );
163 6         7 chomp $line;
164 6         17 $line;
165             }
166 2         9 }
167              
168             sub concat {
169 1     1 1 3 my ($s, @ss) = @_; # streams
170 1         1 my @v;
171             sub {
172 11     11   7 while (1) {
173 12 100       12 @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   8  
199 2         3 my $index = -1;
200 10010     10010   9902 sub { $ring[ ( $index += 1 ) %= @ring ] }
201 2         13 }
202              
203             sub range {
204 14   33 14 1 40 my $begin = shift // croak "range begin undefined";
205 14         14 my $end = shift;
206 14   100     27 my $step = shift // 1;
207              
208 14 50   0   27 return sub { () } if $step == 0;
  0         0  
209              
210 14         11 $begin -= $step;
211 14 100       20 if (defined $end) {
212 9 100       12 if ($step > 0) {
213 22 100   22   64 sub { (($begin += $step) <= $end) ? ($begin) : () }
214 6         33 } else {
215 8 100   8   22 sub { (($begin += $step) >= $end) ? ($begin) : () }
216 3         15 }
217             } else {
218 15     15   17 sub { ($begin += $step) }
219 5         21 }
220             }
221              
222              
223             sub tuple ($$) {
224 6     6 0 4110 my ( $n, $i ) = @_;
225 6 100       443 croak "$n is not a valid parameter for tuple()" if $n <= 0;
226 3         7 $i = _buffer $i;
227             sub {
228 9     9   12 my @v = fold take $n, $i;
229 9 100       39 @v ? \@v : ();
230             }
231 3         19 }
232              
233             sub nth {
234 0     0 1   my ( $n, $s ) = @_;
235 0           $n--;
236 0           take 1, drop $n, $s
237             }
238              
239             sub chunksOf ($$;$) {
240              
241 0     0 1   my ( $n, $src, $offset ) = @_;
242 0 0         $n > 1 or die "chunksOf must be at least 1 (don't forget unfold)";
243 0   0       $offset //= 0;
244              
245 0           my ( $end , $exhausted , $from, $to )
246             = ( $#$src , 0 );
247              
248             sub {
249 0 0   0     return if $exhausted;
250              
251 0           ( $from , $offset )=
252             ( $offset , $offset + $n );
253              
254 0 0         $end <= ($to = $offset - 1) and do {
255 0           $exhausted=1;
256 0           $to = $end;
257             };
258              
259 0           [ @{$src}[$from..$to] ];
  0            
260             }
261 0           }
262              
263              
264             1;
265