File Coverage

lib/List/Gen/Perl6.pm
Criterion Covered Total %
statement 44 49 89.8
branch 13 14 92.8
condition 10 12 83.3
subroutine 11 12 91.6
pod 0 1 0.0
total 78 88 88.6


line stmt bran cond sub pod time code
1             package List::Gen::Perl6;
2 1     1   543 use strict;
  1         2  
  1         37  
3 1     1   5 use warnings;
  1         2  
  1         36  
4 1     1   6 use lib '../../';
  1         2  
  1         9  
5 1     1   131 use List::Gen ();
  1         3  
  1         17  
6 1     1   917 use Filter::Simple;
  1         26035  
  1         9  
7 1     1   57 use Carp ();
  1         3  
  1         40  
8             BEGIN {
9 1     1   7 FILTER_ONLY all => \&_filter_hyper,
10             code_no_comments => \&_filter_rest;
11             }
12             my ($ops) = map qr/(?:[Rr]?(?:$_))/, join '|', map quotemeta, ',', qw (
13             - + / * ** x % . & | ^ < > << >> <=> cmp lt gt eq ne le ge == != <= >=
14             );
15             sub _filter_hyper {
16 1     1   920 s/ ((?:<<|>>)~?) ($ops) (<<|>>) /$1'$2'$3/gx;
17             }
18             sub _filter_rest {
19 1     1   260871 s{
20             (?
21             \[ (\.\.|\\)? ($ops) \]
22             (?= \s* (?! -> | \b(?:$ops)\b(?!>) | [;\)\]\}\>] ) )
23             }{
24 10   100     44 my $t = $1 || '';
25 10 100       21 $t = '..' if $t eq '\\';
26 10         66 "List::Gen::Perl6::_reduceWith '$t$2', "
27             }egx;
28 1         70 s{
29             (?
30             \[ (\.\.|\\)? ($ops) \]
31             (?!>)
32             }{
33 4   100     19 my $t = $1 || '';
34 4 100       12 $t = '..' if $t eq '\\';
35 4         29 "List::Gen::Perl6::_reduction('$t$2')"
36             }gxe;
37 1         71 s{
38             (?
39             }{
40 6 100 66     31 my $rev = $1||$2 ? '~' : '';
41 6 100       38 $3 ? "|$rev'$3'|" : '|'
42             }gxe;
43 1         81 s{
44             (?
45             }{
46 5 100 66     25 my $rev = $1||$2 ? '~' : '';
47 5 100       35 $3 ? "x$rev'$3'x" : 'x'
48             }gxe;
49             }
50              
51             my %cache;
52             sub _reduction {
53 14     14   193 my $str = "[@_]";
54 14   100     17 {return $cache{$str} || next}
  14         56  
55 8         10 local $@;
56 8         12 my $ret = eval {&List::Gen::glob($str)};
  8         25  
57 8 50       41 ref $ret eq 'CODE' or Carp::croak("not a generator glob: $str\n$@\n");
58 8         39 $cache{$str} = $ret;
59             }
60             sub _reduceWith {
61 10     10   284 goto &{_reduction shift}
  10         22  
62             }
63             sub filter {
64 0     0 0   my $str = shift;
65 0           for ($str) {
66 0           _filter_hyper;
67 0           _filter_rest;
68             }
69 0           return $str;
70             }
71              
72             =head1 NAME
73              
74             List::Gen::Perl6 - perl6 meta operators in perl5
75              
76             =head1 SYNOPSIS
77              
78             many of the features found in L borrow ideas from perl6. however,
79             since the syntax of perl5 and perl6 differ, some of the constructs in perl5 are
80             longer/messier than in perl6. C< List::Gen::Perl6 > is a source filter that
81             makes some of C's features more syntactic.
82              
83             the new syntactic constructs are:
84              
85             zip: generator Z generator
86             zipwith: generator Z+ generator
87             cross: generator X generator
88             crosswith: generator X+ generator
89             hyper: generator <<+>> generator
90             hyper: generator >>+<< generator
91             hyper: generator >>+>> generator
92             hyper: generator <<+<< generator
93             reduce: [+] list
94             triangular reduction: [\+] list
95             or [..+] list
96              
97             in the above, C< + > can be any perl binary operator.
98              
99             here is a table showing the correspondence between the source filter constructs,
100             the native overloaded ops, and the operation expanded into methods and functions.
101              
102             List::Gen::Perl6 List::Gen List::Gen expanded
103              
104             <1..3> Z <4..6> ~~ <1..3> | <4..6> ~~ <1..3>->zip(<4..6>)
105              
106             <1..3> Z. <4..6> ~~ <1..3> |'.'| <4..6> ~~ <1..3>->zip('.' => <4..6>)
107              
108             <1..3> X <4..6> ~~ <1..3> x <4..6> ~~ <1..3>->cross(<4..6>)
109              
110             <1..3> X. <4..6> ~~ <1..3> x'.'x <4..6> ~~ <1..3>->cross('.' => <4..6>)
111              
112             <1..3> <<+>> <4..6> ~~ <1..3> <<'+'>> <4..6> ~~ <1..3>->hyper('<<+>>', <4..6>)
113              
114             [+] 1..10 ~~ <[+] 1..10> ~~ reduce {$_[0] + $_[1]} 1 .. 10
115             [+]->(1..10) ~~ <[+]>->(1..10) ~~ same as above
116              
117             [\+] 1..10 ~~ <[..+] 1..10> ~~ scan {$_[0] + $_[1]} 1 .. 10
118             [\+]->(1..10) ~~ <[..+]>->(1..10) ~~ same as above
119              
120             except for normal reductions C< [+] >, all of the new constructs return a
121             generator.
122              
123             you can flip the arguments to an operator with C< R > or C< r > and in some
124             cases C< ~ >
125              
126             ZR. Zr. Z~.
127             XR. Xr. X~.
128             <> <> <<~.>>
129             [R.] [r.] n/a
130             [\R.] [\r.] n/a
131              
132             when used without a following argument, reductions and triangular reductions
133             will return a code reference that will perform the reduction on its arguments.
134              
135             my $sum = [+];
136             say $sum->(1..10); # 55
137              
138             reductions can take a list of scalars, or a single generator as their argument.
139              
140             only the left hand side of the zip, cross, and hyper operators needs to be a
141             generator. zip and cross will upgrade their rhs to a generator if it is an array.
142             hyper will upgrade it's rhs to a generator if it is an array or a scalar.
143              
144             the source filter is limited in scope, and should not harm other parts of the code,
145             however, source filters are notoriously difficult to fully test, so take that
146             with a grain of salt. due to limitations of L, hyper operators
147             will be filtered in both code and strings. all other filters should skip strings.
148              
149             this code is not really intended for serious work, ymmv.
150              
151             =head1 AUTHOR
152              
153             Eric Strom, C<< >>
154              
155             =head1 BUGS
156              
157             report any bugs / feature requests to C, or through
158             the web interface at L.
159              
160             comments / feedback / patches are also welcome.
161              
162             =head1 COPYRIGHT & LICENSE
163              
164             copyright 2009-2011 Eric Strom.
165              
166             this program is free software; you can redistribute it and/or modify it under
167             the terms of either: the GNU General Public License as published by the Free
168             Software Foundation; or the Artistic License.
169              
170             see http://dev.perl.org/licenses/ for more information.
171              
172             =cut
173              
174             1