File Coverage

blib/lib/Language/Functional.pm
Criterion Covered Total %
statement 391 418 93.5
branch 84 138 60.8
condition 8 18 44.4
subroutine 104 105 99.0
pod 61 72 84.7
total 648 751 86.2


line stmt bran cond sub pod time code
1             package Language::Functional;
2              
3 1     1   6194 use strict;
  1         2  
  1         32  
4 1     1   8 use warnings;
  1         2  
  1         30  
5 1     1   5 use Carp;
  1         3  
  1         55  
6 1     1   13 no strict 'refs';
  1         1  
  1         34  
7 1     1   5 use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS $INFINITE);
  1         2  
  1         4675  
8             require Exporter;
9              
10             @ISA = qw(Exporter);
11             $VERSION = '0.05';
12             $INFINITE = 8192;
13              
14             my @methods = qw(show inc double square cons max min even odd
15             rem quot gcd lcm Until
16             id const flip fst snd head Last tail init
17             null Map filter Length concat
18             foldl foldl1 scanl scanl1
19             foldr foldr1 scanr scanr1
20             iterate repeat replicate
21             take drop splitAt takeWhile dropWhile span break
22             lines words unlines unwords Reverse
23             And Or any all elem notElem lookup maximum minimum
24             sum product zip zip3 unzip unzip3
25             integers factors prime
26             );
27              
28             @EXPORT_OK = @methods;
29             %EXPORT_TAGS = ('all', => \@methods);
30              
31              
32             =head1 NAME
33              
34             Language::Functional - a module which makes Perl slightly more functional
35              
36             =head1 SYNOPSIS
37              
38             use Language::Functional ':all';
39             print 'The first ten primes are: ',
40             show(take(10, filter { prime(shift) } integers)), "\n";
41              
42             =head1 DESCRIPTION
43              
44             Perl already contains some functional-like functions, such as
45             C and C. The purpose of this module is to add other
46             functional-like functions to Perl, such as foldl and foldr, as
47             well as the use of infinite lists.
48              
49             Think as to how you would express the first ten prime
50             numbers in a simple way in your favourite programming
51             language? So the example in the synopsis is a killer app,
52             if you will (until I think up a better one ;-).
53              
54             The idea is mostly based on Haskell, from which most of the
55             functions are taken. There are a couple of major omissions:
56             currying and types. Lists (and tuples) are simply Perl list
57             references, none of this 'cons' business, and strings are
58             simple strings, not lists of characters.
59              
60             The idea is to make Perl slightly more functional, rather
61             than completely replace it. Hence, this slots in very well
62             with whatever else your program may be doing, and is very
63             Perl-ish. Other modules are expected to try a much more
64             functional approach.
65              
66             =head1 FUNCTIONS
67              
68             The following functions are available. (Note: these should not be
69             called as methods).
70              
71             In each description, I shall give the Haskell definition
72             (if I think it would help) as well as a useful example.
73              
74             =over 4
75              
76             =cut
77              
78             # Insert copious amounts of POD documentation here for each
79             # function... (test.pl will have to do for now)
80              
81             sub show_old {
82 0         0 join ", ",
83             map {
84 0     0 0 0 my $d = Data::Dumper->new([$_]);
85 0         0 $d->Indent(0)->Terse(1);
86 0         0 $d->Dump;
87             } @_;
88             }
89              
90              
91             =item show
92              
93             Show returns a string representation of an object.
94             It does not like infinite lists.
95              
96             =cut
97              
98             sub show {
99 136     136 1 718 return join ", ", map {show_aux($_)} @_;
  356         548  
100             }
101              
102             sub show_aux {
103 356     356 0 381 my $x = shift;
104 356 50       1200 if (not defined $x) {
    100          
    100          
    50          
105 0         0 return 'undef';
106             } elsif ($x eq '') {
107 3         17 return "''";
108             } elsif (not ref $x) {
109 301 100       1242 if ($x =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) {
    100          
110 293         1269 return "$x";
111             } elsif ($x =~ /^.$/) {
112 3         14 return "'$x'";
113             } else {
114 5         11 $x =~ s|\n|\\n|g;
115 5         28 return '"' . $x . '"';
116             }
117             } elsif (ref($x) eq 'ARRAY') {
118             # Here we evaluate all values of the array. As this can
119             # be lazy, and might resize the array, we have to do this
120             # now.
121 52 100       70 map { $x->[$_] if $_ < scalar @{$x}} (0..scalar @{$x});
  20806         19923  
  20806         42115  
  52         126  
122             # return "(Array of size " . scalar @{$x} . ", " . ref($x) . ")" . "[" . show(@{$x}) . "]";
123 50         472 return "[" . show(@{$x}) . "]";
  50         110  
124             } else {
125 0         0 return "[ref $x]";
126             }
127             }
128              
129              
130             =item inc k
131              
132             Increases the value passed by 1.
133              
134             $x = inc 2; # 3
135              
136             In Haskell:
137              
138             inc :: a -> a
139             inc k = 1 + k
140              
141             =cut
142              
143             sub inc($) {
144 10     10 1 51 return shift() + 1;
145             }
146              
147              
148             =item double k
149              
150             Doubles the passed value.
151              
152             $x = double 3; # 6
153              
154             In Haskell:
155              
156             double :: a -> a
157             double k = k * 2
158              
159             =cut
160              
161             sub double($) {
162 7     7 1 30 return shift() * 2;
163             }
164              
165              
166             =item square k
167              
168             Returns the square of the passed value. eg:
169              
170             $x = square 3; # 9
171              
172             In Haskell:
173              
174             square :: a -> a
175             square k = k * k
176              
177             =cut
178              
179             sub square($) {
180 11     11 1 32 return shift() ** 2;
181             }
182              
183             sub cons {
184 1     1 0 2 unshift @{$_[1]}, $_[0];
  1         4  
185 1         3 return ($_[1]);
186             }
187              
188             sub min($$) {
189 6     6 0 8 my($x, $y) = @_;
190 6 50       19 return $x if $x < $y;
191 0         0 return $y;
192             }
193              
194             sub max($$) {
195 9     9 0 10 my($x, $y) = @_;
196 9 50       23 return $x if $x > $y;
197 9         22 return $y;
198             }
199              
200             sub even($) {
201 8233     8233 0 10062 my $x = shift;
202 8233         30572 return not $x % 2;
203             }
204              
205             sub odd($) {
206 8223     8223 0 16234 my $x = shift;
207 8222         26369 return not even($x);
208             }
209              
210             sub rem($$) {
211 6     6 0 6 my($x, $y) = @_;
212 6         20 return $x % $y;
213             }
214              
215             sub quot($$) {
216 1     1 0 2 my($x, $y) = @_;
217 1         4 return int($x/$y);
218             }
219              
220              
221             =item gcd x y
222              
223             Returns the greatest common denominator of two
224             numbers. eg:
225              
226             $x = gcd(144, 1024); # 16
227              
228             In Haskell:
229              
230             gcd :: Integral a => a -> a -> a
231             gcd 0 0 = error "gcd 0 0 is undefined"
232             gcd x y = gcd' (abs x) (abs y)
233             where gcd' x 0 = x
234             gcd' x y = gcd' y (x `rem` y)
235              
236             =cut
237              
238             sub gcd($$) {
239 2     2 1 3 my($x, $y) = @_;
240 2 50 33     6 croak "gcd(0, 0) is undefined!" if ($x == 0 and $y == 0);
241 2         6 return gcd_aux(abs $x, abs $y);
242             }
243              
244             sub gcd_aux($$);
245             sub gcd_aux($$) {
246 8     8 0 9 my($x, $y) = @_;
247 8 100       20 return $x if $y == 0;
248 6         11 return gcd_aux($y, rem($x, $y));
249             }
250              
251              
252             =item lcm x y
253              
254             Returns the lowest common multiple of two numbers.
255             eg:
256              
257             $x = lcm(144, 1024); # 9216
258              
259             In Haskell:
260              
261             lcm :: (Integral a) => a -> a -> a
262             lcm _ 0 = 0
263             lcm 0 _ = 0
264             lcm x y = abs ((x `quot` gcd x y) * y)
265              
266             =cut
267              
268             sub lcm($$) {
269 1     1 1 1 my($x, $y) = @_;
270 1 50       5 return 0 if $x == 0;
271 1 50       3 return 0 if $y == 0;
272 1         7 return abs((quot($x,gcd($x, $y))) * $y);
273             }
274              
275              
276             =item id x
277              
278             The identity function - simply returns the argument.
279             eg:
280              
281             $x = id([1..6]); # [1, 2, 3, 4, 5, 6].
282              
283             In Haskell:
284              
285             id :: a -> a
286             id x = x
287              
288             =cut
289              
290             sub id {
291 1     1 1 2 my @values = @_;
292 1         3 return @values;
293             }
294              
295              
296             =item const k _
297              
298             Returns the first argument of 2 arguments. eg:
299              
300             $x = const(4, 5); # 4
301              
302             In Haskell:
303              
304             const :: a -> b -> a
305             const k _ = k
306              
307             =cut
308              
309             sub const {
310 1     1 1 2 my $x = shift;
311 1         4 return $x;
312             }
313              
314              
315             =item flip f
316              
317             Given a function, flips the two arguments it is passed.
318             Note that this returns a CODEREF, as currying does not yet
319             happen. eg: flip(sub { $_[0] ** $_[1] })->(2, 3) = 9.
320             In Haskell (ie this is what it should really do):
321              
322             flip :: (a -> b -> c) -> b -> a -> c
323             flip f x y = f y x
324              
325             =cut
326              
327             sub flip {
328 1     1 1 3 my $f = shift;
329             return sub {
330 1     1   8 $f->($_[1], $_[0]);
331             }
332 1         5 }
333             # flip f x y -> f y x can't be done as
334             # this isn't yet lazy or curried!
335              
336              
337             =item Until p f x
338              
339             Keep on applying f to x until p(x) is true, and
340             then return x at that point. eg:
341              
342             $x = Until { shift() % 10 == 0 } \&inc, 1; # 10
343              
344             In Haskell:
345              
346             until :: (a -> Bool) -> (a -> a) -> a -> a
347             until p f x = if p x then x else until p f (f x)
348              
349             =cut
350              
351             sub Until(&&$);
352             sub Until(&&$) {
353 10     10 1 15 my($p, $f, $x) = @_;
354 10 100       19 return $x if $p->($x);
355 9         48 return Until(\&$p, \&$f, $f->($x));
356             }
357              
358              
359             =item fst x:xs
360              
361             Returns the first element in a tuple. eg:
362              
363             $x = fst([1, 2]); # 1
364              
365             In Haskell:
366              
367             fst :: (a,b) -> a
368             fst (x,_) = x
369              
370             =cut
371              
372             sub fst($) {
373 1     1 1 2 my $x = shift;
374 1         4 return $x->[0];
375             }
376              
377              
378             =item snd x:y:xs
379              
380             Returns the second element in a tuple. eg:
381              
382             $x = snd([1, 2]); # 2
383              
384             In Haskell:
385              
386             snd :: (a,b) -> a
387             snd (_,y) = y
388              
389             =cut
390              
391             sub snd($) {
392 1     1 1 2 my $x = shift;
393 1         3 return $x->[1];
394             }
395              
396              
397             =item head xs
398              
399             Returns the head (first element) of a list. eg:
400              
401             $x = head([1..6]); # 1
402              
403             In Haskell:
404              
405             head :: [a] -> a
406             head (x:_) = x
407              
408             =cut
409              
410             sub head($) {
411 2     2 1 3 my $xs = shift;
412 2         10 return $xs->[0];
413             }
414              
415              
416             =item Last xs
417              
418             Returns the last element of a list. Note the capital L, to make it
419             distinct from the Perl 'last' command. eg:
420              
421             $x = Last([1..6]); # 6
422              
423             In Haskell:
424              
425             last :: [a] -> a
426             last [x] = x
427             last (_:xs) = last xs
428              
429             =cut
430              
431             sub Last($) {
432 2     2 1 3 my $xs = shift;
433 2         8 return $xs->[-1];
434             }
435              
436              
437             =item tail xs
438              
439             Returns a list minus the first element (head). eg:
440              
441             $x = tail([1..6]); # [2, 3, 4, 5, 6]
442              
443             In Haskell:
444              
445             tail :: [a] -> [a]
446             tail (_:xs) = xs
447              
448             =cut
449              
450             sub tail($) {
451 3     3 1 335 my $xs = shift;
452 3         5 my $len = scalar @{$xs};
  3         7  
453 3 100       9 $len = $len == $INFINITE ? $len : $len - 1;
454             tie my @a, 'InfiniteList', sub {
455 8201     8201   9159 my($array, $idx) = @_;
456 8201         20618 return $xs->[$idx+1];
457 3         17 }, $len;
458 3         11 return \@a;
459             }
460              
461              
462             =item init xs
463              
464             Returns a list minus its last element. eg:
465              
466             $x = init([1..6]); # [1, 2, 3, 4, 5]
467              
468             In Haskell:
469              
470             init :: [a] -> [a]
471             init [x] = []
472             init (x:xs) = x : init xs
473              
474             =cut
475              
476             sub init($) {
477 2     2 1 1391 my $xs = shift;
478 2         2 pop(@{$xs});
  2         16  
479 1         4 return $xs;
480             }
481              
482              
483             =item null xs
484              
485             Returns whether or not the list is empty. eg:
486              
487             $x = null([1, 2]); # False
488              
489             In Haskell:
490              
491             null :: [a] -> Bool
492             null [] = True
493             null (_:_) = False
494              
495             =cut
496              
497             sub null($) {
498 3     3 1 366 my $x = shift;
499 3         4 return not @{$x};
  3         9  
500             }
501              
502              
503             =item Map f xs
504              
505             Evaluates f for each element of the list xs and returns the list
506             composed of the results of each such evaluation. It is very similar to
507             the Perl command 'map', hence the capital M, but also copes with
508             infinite lists. eg:
509              
510             $x = Map { double(shift) } [1..6]; # [2, 4, 6, 8, 10, 12]
511              
512             In Haskell:
513              
514             map :: (a -> b) -> [a] -> [b]
515             map f xs = [ f x | x <- xs ]
516              
517             =cut
518              
519             sub Map(&$) {
520 2     2 1 3 my($f, $xs) = @_;
521             tie my @a, 'InfiniteList', sub {
522 16     16   16 my($array, $idx) = @_;
523 16         40 return $f->($xs->[$idx]);
524 2         8 }, scalar @{$xs};
  2         6  
525 2         7 return \@a;
526             }
527              
528              
529             =item filter p xs
530              
531             Returns the list of the elements in xs for which
532             p(xs) returns true. It is similar to the Perl command
533             'grep', but it also copes with infinite lists. eg:
534              
535             $x = filter(\&even, [1..6]); # [2, 4, 6]
536              
537             In Haskell:
538              
539             filter :: (a -> Bool) -> [a] -> [a]
540             filter p xs = [ x | x <- xs, p x ]
541              
542             =cut
543              
544             # Ha! Before infinite lists simply consisted of:
545             # return [grep { $f->($_) } @{$xs}];
546              
547             sub filter(&$) {
548 5     5 1 11 my($f, $xs) = @_;
549 5         10 my $pointer = -1;
550             tie my @a, 'InfiniteList', sub {
551 4125     4125   5328 my($array, $idx) = @_;
552 4125         4302 my $debug = 0;
553 4125 50       6752 print "$idx: in (done $pointer)\n" if $debug;
554 4125 50       8764 if ($pointer eq $INFINITE) {
555 0         0 die "Fetching an infinite amount of values in filter()!\n";
556             }
557 4125 50       9387 if ($idx - 1 > $pointer) {
558 0 0       0 print "$idx: doing $array->FETCH for $pointer..", $idx - 1, "\n" if $debug;
559 0 0       0 map { $array->FETCH($_) if $_ < $array->FETCHSIZE} ($pointer..$idx-1);
  0         0  
560             }
561 4125 50       7477 if ($idx > $array->FETCHSIZE) {
562 0 0       0 print "$idx: in: silly, getting out\n" if $debug;
563 0         0 return undef;
564             }
565 4125         4738 while (1) {
566 8254         8799 $pointer++;
567 8254 50       16738 print "$idx: loop: $idx (done $pointer/", $array->FETCHSIZE, ") = ", $f->($xs->[$pointer]), "\n" if $debug;
568 8254 100       25112 if ($pointer >= $array->FETCHSIZE) {
569 2 50       5 print "$idx: Size *was* ", $array->FETCHSIZE, "!\n" if $debug;
570 2         6 $array->STORESIZE($idx);
571 2 50       4 print "$idx: Set size to ", $array->FETCHSIZE, "!\n" if $debug;
572 2         3 last;
573             }
574 8252 100       21036 if ($f->($xs->[$pointer])) {
575 4122 50       6771 print "$idx: oooh (elt $pointer: '", $xs->[$pointer], "' was true)\n" if $debug;
576 4122         4887 last;
577             }
578             }
579 4124 50       14021 print "$idx: loop: out\n" if $debug;
580              
581 4124         10662 return $xs->[$pointer];
582 5         32 }, scalar @{$xs};
  5         19  
583 5         25 return \@a;
584             }
585              
586              
587             =item concat
588              
589             Concatenates lists together into one list. eg:
590              
591             concat([[1..3], [4..6]]); # [1, 2, 3, 4, 5, 6]
592              
593             In Haskell:
594              
595             concat :: [[a]] -> [a]
596             concat = foldr (++) []
597              
598             TODO: Make sure this works with infinite lists!
599              
600             =cut
601              
602             sub concat($) {
603 1     1 1 3 my($xxs) = shift;
604 1     2   8 return foldr(sub { [@{shift()}, @{shift()}]; }, [], $xxs);
  2         3  
  2         3  
  2         8  
605             }
606              
607              
608             =item Length
609              
610             Returns the length of a list - only do this with
611             finite lists! eg:
612              
613             $x = Length([1..6]); # 6
614              
615             In Haskell:
616              
617             length :: [a] -> Int
618             length = foldl' (\n _ -> n + 1) 0
619              
620             TODO Make sure this works!
621              
622             =cut #'
623              
624             sub Length($) {
625 37     37 1 44 my $xs = shift;
626 37         35 my $len = scalar @{$xs};
  37         48  
627 37 100       318 confess "Fetching the length of an infinite list!"
628             if $len == $INFINITE;
629 36         125 return $len;
630             }
631              
632              
633             =item foldl f z xs
634              
635             Applies function f to the pairs (z, xs[0]), (f(z, xs[0], xs[1]),
636             (f(f(z, xs[0], xs[1])), xs[2]) and so on. ie it folds from the left
637             and returns the last value. Note that foldl should not be done to
638             infinite lists. eg: the following returns the sum of 1..6:
639              
640             $x = foldl { shift() + shift() } 0, [1..6]; # 21
641              
642             In Haskell:
643              
644             foldl :: (a -> b -> a) -> a -> [b] -> a
645             foldl f z [] = z
646             foldl f z (x:xs) = foldl f (f z x) xs
647              
648             =cut
649              
650             sub foldl(&$$) {
651 8     8 1 308 my($f, $z, $xs) = @_;
652 8         9 map { $z = $f->($z, $_) } @{$xs};
  41         107  
  8         12  
653 8         37 return $z;
654             }
655              
656              
657             =item foldl1 f xs
658              
659             This is a variant of foldl where the first value of
660             xs is taken as z. Applies function f to the pairs (xs[0], xs[1]),
661             (f(xs[0], xs[1], xs[2]), (f(f(xs[0], xs[1], xs[2])), xs[3]) and
662             so on. ie it folds from the left and returns the last value.
663             Note that foldl should not be
664             done to infinite lists. eg: the following returns the sum
665             of 1..6:
666              
667             $x = foldl1 { shift() + shift() } [1..6]; # 21
668              
669             In Haskell:
670              
671             foldl1 :: (a -> a -> a) -> [a] -> a
672             foldl1 f (x:xs) = foldl f x xs
673              
674             =cut
675              
676             sub foldl1(&$) {
677 6     6 1 9 my($f, $xs) = @_;
678 6         15 my $z = shift @{$xs};
  6         25  
679 4         11 return foldl(\&$f, $z, $xs);
680             }
681              
682              
683             =item scanl f q xs
684              
685             Returns a list of all the intermedia values that foldl would compute.
686             ie returns the list z, f(z, xs[0]), f(f(z, xs[0]), xs[1]), f(f(f(z,
687             xs[0]), xs[1]), xs[2]) and so on. eg:
688              
689             $x = scanl { shift() + shift() }, 0, [1..6]; # [0, 1, 3, 6, 10, 15, 21]
690              
691             In Haskell:
692              
693             scanl :: (a -> b -> a) -> a -> [b] -> [a]
694             scanl f q xs = q : (case xs of
695             [] -> []
696             x:xs -> scanl f (f q x) xs)
697              
698             =cut
699              
700             sub scanl(&$$) {
701 3     3 1 511 my($f, $q, $xs) = @_;
702             # Ha! Before infinite lists simply consisted of the elegant:
703             # my @return = $q;
704             # map { $q = $f->($q, $_); push @return, $q } @{$xs};
705             # return [@return];
706 3         6 my $pointer = -1;
707             tie my @a, 'InfiniteList', sub {
708 19     19   23 my($array, $idx) = @_;
709 19         20 my $debug = 0;
710 19 50       37 print "$idx: in (done $pointer)\n" if $debug;
711 19 100       34 if ($idx == 0) {
712 3 50       26 print "$idx: zero, easy = $q!\n" if $debug;
713 3         10 return $q;
714             }
715 16 50       34 if ($pointer eq $INFINITE) {
716 0         0 die "Fetching an infinite amount of values in filter()!\n";
717             }
718 16 50       38 if ($idx - 1 > $pointer) {
719 16 50       24 print "$idx: doing $array->FETCH for $pointer..", $idx - 1, "\n" if $debug;
720 16 50       27 map { $array->FETCH($_) if $_ < $array->FETCHSIZE} ($pointer..$idx-1);
  32         65  
721             }
722 16 50       33 if ($idx > $array->FETCHSIZE) {
723 0 0       0 print "$idx: in: silly, getting out\n" if $debug;
724 0         0 return undef;
725             }
726 16         19 $pointer++;
727 16 50       29 print "$idx: getting f(idx $idx-1, ", $xs->[$idx-1], "\n" if $debug;
728 16         35 my $return = $f->($array->FETCH($idx-1), $xs->[$idx-1]);
729 16 50       64 print "$idx: out with $return\n" if $debug;
730 16         39 return $return;
731 3         20 }, scalar @{$xs} + 1;
  3         14  
732 3         16 return \@a;
733             }
734              
735              
736             =item scanl1 f xs
737              
738             This is a variant of scanl where the first value of xs is taken as
739             q. Returns a list of all the intermedia values that foldl would
740             compute. ie returns the list f(xs[0], xs[1]), f(f(xs[0], xs[1]),
741             xs[2]), f(f(f(xs[0], xs[1]), xs[2]), xs[3]) and so on. eg:
742              
743             $x = scanl1 { shift() + shift() } [1..6]; # [1, 3, 6, 10, 15, 21]
744              
745             In Haskell:
746              
747             scanl1 :: (a -> a -> a) -> [a] -> [a]
748             scanl1 f (x:xs) = scanl f x xs
749              
750             =cut
751              
752             sub scanl1(&$) {
753 3     3 1 6 my($f, $xs) = @_;
754 3         3 my $z = shift @{$xs};
  3         9  
755 2         11 return scanl(\&$f, $z, $xs);
756             }
757              
758              
759             =item foldr f z xs
760              
761             This is similar to foldl but is folding from the right instead of the
762             left. Note that foldr should not be done to infinite lists. eg: the
763             following returns the sum of 1..6
764              
765             $x = foldr { shift() + shift() } 0, [1..6] ; # 21
766              
767             In Haskell:
768              
769             foldr :: (a -> b -> b) -> b -> [a] -> b
770             foldr f z [] = z
771             foldr f z (x:xs) = f x (foldr f z xs)
772              
773             =cut
774              
775             sub foldr(&$$) {
776 5     5 1 554 my($f, $z, $xs) = @_;
777 5         9 map { $z = $f->($_, $z) } reverse @{$xs};
  17         45  
  5         12  
778 5         30 return $z;
779             }
780              
781              
782             =item foldr1 f xs
783              
784             This is similar to foldr1 but is folding from the right instead of the
785             left. Note that foldr1 should not be done on infinite lists. eg:
786              
787             $x = foldr1 { shift() + shift() } [1..6]; # 21
788              
789             In Haskell:
790              
791             foldr1 :: (a -> a -> a) -> [a] -> a
792             foldr1 f [x] = x
793             foldr1 f (x:xs) = f x (foldr1 f xs)
794              
795             =cut
796              
797             sub foldr1(&$) {
798 3     3 1 6 my($f, $xs) = @_;
799 3         5 my $z = pop @{$xs};
  3         6  
800 3         10 return foldr(\&$f, $z, $xs);
801             }
802              
803              
804             =item scanr f z xs
805              
806             This is similar to scanl but is scanning and folding
807             from the right instead of the left. Note that scanr should
808             not be done on infinite lists. eg:
809              
810             $x = scanr { shift() + shift() } 0, [1..6];
811             # [0, 6, 11, 15, 18, 20, 21]
812              
813             In Haskell:
814              
815             scanr :: (a -> b -> b) -> b -> [a] -> [b]
816             scanr f q0 [] = [q0]
817             scanr f q0 (x:xs) = f x q : qs
818             where qs@(q:_) = scanr f q0 xs
819              
820             =cut
821              
822             sub scanr(&$$) {
823 2     2 1 3 my($f, $z, $xs) = @_;
824 2         5 my @return = $z;
825 2         3 map { $z = $f->($_, $z); push @return, $z; } reverse @{$xs};
  11         20  
  11         33  
  2         4  
826 2         10 return [@return];
827             }
828              
829              
830             =item scanr1 f xs
831              
832             This is similar to scanl1 but is scanning and folding
833             from the right instead of the left. Note that scanr1 should
834             not be done on infinite lists. eg:
835              
836             $x = scanr1 { shift() + shift() } [1..6];
837             # [6, 11, 15, 18, 20, 21]
838              
839             In Haskell:
840              
841             scanr1 :: (a -> a -> a) -> [a] -> [a]
842             scanr1 f [x] = [x]
843             scanr1 f (x:xs) = f x q : qs
844             where qs@(q:_) = scanr1 f xs
845              
846             =cut
847              
848             sub scanr1(&$) {
849 1     1 1 2 my($f, $xs) = @_;
850 1         2 my $z = pop @{$xs};
  1         2  
851 1         4 return scanr(\&$f, $z, $xs);
852             }
853              
854              
855             =item iterate f x
856              
857             This returns the infinite list (x, f(x), f(f(x)), f(f(f(x)))...) and
858             so on. eg:
859              
860             $x = take(8, iterate { shift() * 2 } 1);
861             # [1, 2, 4, 8, 16, 32, 64, 128]
862              
863             In Haskell:
864              
865             iterate :: (a -> a) -> a -> [a]
866             iterate f x = x : iterate f (f x)
867              
868             =cut
869              
870             sub iterate(&$) {
871 27     27 1 46 my($f, $x) = @_;
872             tie my @a, 'InfiniteList', sub {
873 32900     32900   37815 my($array, $idx) = @_;
874 32900 100       56377 return $x if $idx == 0;
875 32878         68112 return $f->($array->FETCH($idx-1));
876 27         216 };
877 27         106 return \@a;
878             }
879              
880              
881             =item repeat x
882              
883             This returns the infinite list where all
884             elements are x. eg:
885              
886             $x = take(4, repeat(42)); # [42, 42, 42, 42].
887              
888             In Haskell:
889              
890             repeat :: a -> [a]
891             repeat x = xs where xs = x:xs
892              
893             =cut
894              
895             sub repeat($) {
896 2     2 1 5 my $x = shift;
897             tie my @a, 'InfiniteList', sub {
898 9     9   22 return $x;
899 2         17 };
900 2         11 return \@a;
901             }
902              
903              
904             =item replicate n x
905              
906             Returns a list containing n times the element x. eg:
907              
908             $x = replicate(5, 1); # [1, 1, 1, 1, 1]
909              
910             In Haskell:
911              
912             replicate :: Int -> a -> [a]
913             replicate n x = take n (repeat x)
914              
915             =cut
916              
917             sub replicate($$) {
918 1     1 1 4 my($n, $x) = @_;
919 1         4 return take($n, repeat($x));
920             }
921              
922             # TODO
923             # cycle :: [a] -> [a]
924             # cycle [] = error "Prelude.cycle: empty list"
925             # cycle xs = xs' where xs'=xs++xs'
926              
927              
928             =item take n xs
929              
930             Returns a list containing the first n elements from the list xs. eg:
931              
932             $x = take(2, [1..6]); # [1, 2]
933              
934             In Haskell:
935              
936             take :: Int -> [a] -> [a]
937             take 0 _ = []
938             take _ [] = []
939             take n (x:xs) | n>0 = x : take (n-1) xs
940             take _ _ = error "Prelude.take: negative argument"
941              
942             =cut
943              
944             sub take($$) {
945 16     16 1 32 my($n, $xs) = @_;
946 16         21 my @return;
947 16         42 foreach my $i (0..$n-1) {
948 114         276 push @return, $xs->[$i];
949             }
950 16         73 return \@return;
951             }
952              
953              
954             =item drop n xs
955              
956             Returns a list containing xs with the first n elements missing. eg:
957              
958             $x = drop(2, [1..6]); # [3, 4, 5, 6]
959              
960             In Haskell:
961              
962             drop :: Int -> [a] -> [a]
963             drop 0 xs = xs
964             drop _ [] = []
965             drop n (_:xs) | n>0 = drop (n-1) xs
966             drop _ _ = error "Prelude.drop: negative argument"
967              
968             =cut
969              
970             sub drop($$) {
971 2     2 1 5 my($n, $xs) = @_;
972             # Ha! Before infinite lists simply consisted of:
973             # return [splice @{$xs}, $n];
974 2         3 my $len = scalar @{$xs};
  2         6  
975 2 100       8 $len = $len == $INFINITE ? $len : $len - $n;
976             tie my @a, 'InfiniteList', sub {
977 8     8   11 my($array, $idx) = @_;
978 8         27 return $xs->[$idx+$n];
979 2         15 }, $len;
980 2         11 return \@a;
981             }
982              
983              
984             =item splitAt n xs
985              
986             Splits the list xs into two lists at element n. eg:
987              
988             $x = splitAt(2, [1..6]);# [[1, 2], [3, 4, 5, 6]]
989              
990             In Haskell:
991              
992             splitAt :: Int -> [a] -> ([a], [a])
993             splitAt 0 xs = ([],xs)
994             splitAt _ [] = ([],[])
995             splitAt n (x:xs) | n>0 = (x:xs',xs'') where (xs',xs'') = splitAt (n-1) xs
996             splitAt _ _ = error "Prelude.splitAt: negative argument"
997              
998             =cut
999              
1000             sub splitAt($$) {
1001 1     1 1 3 my($n, $xs) = @_;
1002 1         3 return [take($n, $xs), drop($n, $xs)];
1003             }
1004              
1005              
1006             =item takeWhile p xs
1007              
1008             Takes elements from xs while p(that element) is
1009             true. Returns the list. eg:
1010              
1011             $x = takeWhile { shift() <= 4 } [1..6]; # [1, 2, 3, 4]
1012              
1013             In Haskell:
1014              
1015             takeWhile :: (a -> Bool) -> [a] -> [a]
1016             takeWhile p [] = []
1017             takeWhile p (x:xs)
1018             | p x = x : takeWhile p xs
1019             | otherwise = []
1020              
1021             =cut
1022              
1023             sub takeWhile(&$) {
1024 4     4 1 9 my($p, $xs) = @_;
1025             # Ha! Before infinite lists simply consisted of:
1026             # my @return;
1027             # push @return, $_ while($_ = shift @{$xs} and $p->($_));
1028             # return [@return];
1029 4         6 my $pointer = -1;
1030             tie my @a, 'InfiniteList', sub {
1031 19     19   23 my($array, $idx) = @_;
1032 19         19 my $debug = 0;
1033 19 50       37 print "$idx: in (done $pointer)\n" if $debug;
1034 19 50       40 if ($pointer eq $INFINITE) {
1035 0         0 die "Fetching an infinite amount of values in filter()!\n";
1036             }
1037 19 50       36 if ($idx - 1 > $pointer) {
1038 0 0       0 print "$idx: doing $array->FETCH for $pointer..", $idx - 1, "\n" if $debug;
1039 0 0       0 map { $array->FETCH($_) if $_ < $array->FETCHSIZE} ($pointer..$idx-1);
  0         0  
1040             }
1041 19 50       40 if ($idx > $array->FETCHSIZE) {
1042 0 0       0 print "$idx: in: silly, getting out\n" if $debug;
1043 0         0 return undef;
1044             }
1045 19         22 $pointer++;
1046 19 100       40 if ($p->($xs->[$pointer])) {
1047 15 50       60 print "$idx: p true for index $pointer\n" if $debug;
1048 15         40 return $xs->[$pointer];
1049             } else {
1050 4 50       19 print "$idx: p NOT true for index - resizing to $pointer\n" if $debug;
1051 4         12 $array->STORESIZE($pointer);
1052 4         10 return undef;
1053             }
1054 4         25 }, scalar @{$xs};
  4         15  
1055 4         16 return \@a;
1056             }
1057              
1058              
1059             =item dropWhile p xs
1060              
1061             Drops elements from the head of xs while p(that element) is
1062             true. Returns the list. eg:
1063              
1064             $x = dropWhile { shift() <= 4 } [1..6]; # [5, 6]
1065              
1066             In Haskell:
1067              
1068             dropWhile :: (a -> Bool) -> [a] -> [a]
1069             dropWhile p [] = []
1070             dropWhile p xs@(x:xs')
1071             | p x = dropWhile p xs'
1072             | otherwise = xs
1073              
1074             =cut
1075              
1076             sub dropWhile(&$) {
1077 4     4 1 5 my($p, $xs) = @_;
1078             # Ha! Before infinite lists simply consisted of:
1079             # shift @{$xs} while($_ = @{$xs}[0] and $p->($_));
1080 4         7 my $pointer = 0;
1081 4         4 while (1) {
1082 19 100       39 last unless $p->($xs->[$pointer]);
1083 15         55 $pointer++;
1084             }
1085 4         14 print "Pointer = $pointer\n" if 0;
1086 4         6 my $len = scalar @{$xs};
  4         9  
1087 4 100       12 $len = $len == $INFINITE ? $len : $len - $pointer;
1088             tie my @a, 'InfiniteList', sub {
1089 11     11   12 my($array, $idx) = @_;
1090 11         28 return $xs->[$idx + $pointer];
1091 4         25 }, $len;
1092 4         18 return \@a;
1093             }
1094              
1095              
1096             =item span p xs
1097              
1098             Splits xs into two lists, the first containing the first few elements
1099             for which p(that element) is true. eg:
1100              
1101             $x = span { shift() <= 4 }, [1..6];
1102             # [[1, 2, 3, 4], [5, 6]]
1103              
1104             In Haskell:
1105              
1106             span :: (a -> Bool) -> [a] -> ([a],[a])
1107             span p [] = ([],[])
1108             span p xs@(x:xs')
1109             | p x = (x:ys, zs)
1110             | otherwise = ([],xs)
1111             where (ys,zs) = span p xs'
1112              
1113             =cut
1114              
1115             sub span(&$) {
1116 2     2 1 3 my($p, $xs) = @_;
1117 2         3 my @xs = @{$xs};
  2         5  
1118 2         6 return [takeWhile(\&$p, $xs), dropWhile(\&$p, \@xs)];
1119             }
1120              
1121              
1122             =item break p xs
1123              
1124             Splits xs into two lists, the first containing the first few elements
1125             for which p(that element) is false. eg:
1126              
1127             $x = break { shift() >= 4 }, [1..6]; # [[1, 2, 3], [4, 5, 6]]
1128              
1129             In Haskell:
1130              
1131             break :: (a -> Bool) -> [a] -> ([a],[a])
1132             break p = span (not . p)
1133              
1134             =cut
1135              
1136             sub break(&$) {
1137 1     1 1 2 my($p, $xs) = @_;
1138 1     8   4 return span(sub { not $p->(@_) }, $xs);
  8         15  
1139             }
1140              
1141              
1142             =item lines s
1143              
1144             Breaks the string s into multiple strings, split at line
1145             boundaries. eg:
1146              
1147             $x = lines("A\nB\nC"); # ['A', 'B', 'C']
1148              
1149             In Haskell:
1150              
1151             lines :: String -> [String]
1152             lines "" = []
1153             lines s = let (l,s') = break ('\n'==) s
1154             in l : case s' of [] -> []
1155             (_:s'') -> lines s''
1156              
1157             =cut
1158              
1159             sub lines($) {
1160 1     1 1 3 my $s = shift;
1161 1         10 return [split /\n/, $s];
1162             }
1163              
1164              
1165             =item words s
1166              
1167             Breaks the string s into multiple strings, split at whitespace
1168             boundaries. eg:
1169              
1170             $x = words("hey how random"); # ['hey', 'how', 'random']
1171              
1172             In Haskell:
1173              
1174             words :: String -> [String]
1175             words s = case dropWhile isSpace s of
1176             "" -> []
1177             s' -> w : words s''
1178             where (w,s'') = break isSpace s'
1179              
1180             =cut
1181              
1182             sub words($) {
1183 1     1 1 2 my $s = shift;
1184 1         7 return [split /\s+/, $s];
1185             }
1186              
1187              
1188             =item unlines xs
1189              
1190             Does the opposite of unlines, that is: joins multiple
1191             strings into one, joined by newlines. eg:
1192              
1193             $x = unlines(['A', 'B', 'C']); # "A\nB\nC";
1194              
1195             In Haskell:
1196              
1197             unlines :: [String] -> String
1198             unlines = concatMap (\l -> l ++ "\n")
1199              
1200             (note that strings in Perl are not lists of characters,
1201             so this approach will not actually work...)
1202              
1203             =cut
1204              
1205             sub unlines($) {
1206 1     1 1 3 my $xs = shift;
1207             # return concatMap(sub { return $_[0] . "\n"; }, $xs);
1208 1     2   8 return foldr1(sub { return $_[0] . "\n" . $_[1]; }, $xs);
  2         8  
1209             }
1210              
1211              
1212             =item unwords ws
1213              
1214             Does the opposite of unwords, that is: joins multiple strings into
1215             one, joined by a space. eg:
1216              
1217             $x = unwords(["hey","how","random"]); # 'hey how random'
1218              
1219             In Haskell:
1220              
1221             unwords :: [String] -> String
1222             unwords [] = []
1223             unwords ws = foldr1 (\w s -> w ++ ' ':s) ws
1224              
1225             =cut
1226              
1227             sub unwords($) {
1228 1     1 1 4 my $xs = shift;
1229 1     2   7 return foldr1(sub { return $_[0] . ' ' . $_[1]; }, $xs);
  2         11  
1230             }
1231              
1232              
1233             =item Reverse xs
1234              
1235             Returns a list containing the elements of xs in reverse order. Note
1236             the capital R, so as not to clash with the Perl command 'reverse'.
1237             You should not try to Reverse an infinite list. eg:
1238              
1239             $x = Reverse([1..6]); # [6, 5, 4, 3, 2, 1]
1240              
1241             In Haskell:
1242              
1243             reverse :: [a] -> [a]
1244             reverse = foldl (flip (:)) []
1245              
1246             =cut
1247              
1248             sub Reverse($) {
1249 3     3 1 5 my $xs = shift;
1250 3         5 return [reverse @{$xs}];
  3         12  
1251             }
1252              
1253              
1254             =item And xs
1255              
1256             Returns true if all the elements in xs are true. Returns false
1257             otherwise. Note the capital A, so as not to clash with the Perl
1258             command 'and'. You should not try to And an infinite list (unless you
1259             expect it to fail, as it will short-circuit). eg:
1260              
1261             $x = And([1, 1, 1]); # 1
1262              
1263             In Haskell:
1264              
1265             and :: [Bool] -> Bool
1266             and = foldr (&&) True
1267              
1268             =cut
1269              
1270             sub And($) {
1271 2     2 1 3416 my $xs = shift;
1272 3 50       16 map {
1273 2         106 return 0 if not $_;
1274 2         21 } @{$xs};
1275 1         7 return 1;
1276             }
1277              
1278              
1279             =item Or xs
1280              
1281             Returns true if one of the elements in xs is true. Returns
1282             false otherwise. Note the capital O, so as not to clash with
1283             the Perl command 'or'. You may try to Or an infinite list
1284             as it will short-circuit (unless you expect it to fail, that
1285             is). eg:
1286              
1287             $x = Or([0, 0, 1]); # 1
1288              
1289             In Haskell:
1290              
1291             or :: [Bool] -> Bool
1292             or = foldr (||) False
1293              
1294             =cut
1295              
1296             sub Or($) {
1297 1     1 1 3387 my $xs = shift;
1298 3 100       22 map {
1299 1         6 return 1 if $_;
1300 1         21 } @{$xs};
1301 0         0 return 0;
1302             }
1303              
1304              
1305             =item any p xs
1306              
1307             Returns true if one of p(each element of xs) are true. Returns
1308             false otherwise. You should not try to And an infinite
1309             list (unless you expect it to fail, as it will short-circuit).
1310             eg:
1311              
1312             $x = any { even(shift) } [1, 2, 3]; # 1
1313              
1314             In Haskell:
1315              
1316             any :: (a -> Bool) -> [a] -> Bool
1317             any p = or . map p
1318              
1319             =cut
1320              
1321             sub any(&$) {
1322 3     3 1 8 my($p, $xs) = @_;
1323 3         5 my $n = 0;
1324 3         5 my $size = $#{$xs};
  3         11  
1325 3         26 while ($n <= $size) {
1326 6 100       18 return 1 if $p->($xs->[$n]);
1327 3         11 $n++;
1328             }
1329 0 0 0     0 if ($size == $Language::Functional::INFINITE
1330             or $size == $Language::Functional::INFINITE - 1
1331             ) {
1332 0         0 confess "Evaluating predicate on inifinite number of elements " .
1333             "would never end!";
1334             }
1335 0         0 return 0;
1336             }
1337              
1338              
1339             =item all p xs
1340              
1341             Returns true if all of the p(each element of xs) is true. Returns
1342             false otherwise. You may try to Or an infinite list
1343             as it will short-circuit (unless you expect it to fail, that
1344             is). eg:
1345              
1346             $x = all { odd(shift) } [1, 1, 3]; # 1
1347              
1348             In Haskell:
1349              
1350             all :: (a -> Bool) -> [a] -> Bool
1351             all p = and . map p
1352              
1353             =cut
1354              
1355             sub all(&$) {
1356 4     4 1 9 my($p, $xs) = @_;
1357 4         6 my $n = 0;
1358 4         7 my $size = $#{$xs};
  4         12  
1359 4         16 while ($n <= $size) {
1360 8200 100       16841 return 0 if not $p->($xs->[$n]);
1361 8199         32094 $n++;
1362             }
1363 3 100 66     35 if ($size == $Language::Functional::INFINITE
1364             or $size == $Language::Functional::INFINITE - 1
1365             ) {
1366 1         296 confess "Evaluating predicate on inifinite number of elements " .
1367             "would never end!";
1368             }
1369 2         9 return 1;
1370             }
1371              
1372              
1373             =item elem x xs
1374              
1375             Returns true is x is present in xs.
1376             You probably should not do this with infinite lists.
1377             Note that this assumes x and xs are numbers.
1378             eg:
1379              
1380             $x = elem(2, [1, 2, 3]); # 1
1381              
1382             In Haskell:
1383              
1384             elem :: Eq a => a -> [a] -> Bool
1385             elem = any . (==)
1386              
1387             =cut
1388              
1389             sub elem($$) {
1390 1     1 1 511 my($x, $xs) = @_;
1391 1     2   9 return any(sub { $_[0] == $x }, $xs);
  2         15  
1392             }
1393              
1394              
1395             =item notElem x xs
1396              
1397             Returns true if x is not present in x. You should not do this with
1398             infinite lists. Note that this assumes that x and xs are numbers. eg:
1399              
1400             $x = notElem(2, [1, 1, 3]); # 1
1401              
1402             In Haskell:
1403              
1404             notElem :: Eq a => a -> [a] -> Bool
1405             notElem = all . (/=)
1406              
1407             =cut
1408              
1409             sub notElem($$) {
1410 1     1 1 3 my($x, $xs) = @_;
1411 1     3   6 return all { shift() != $x } $xs;
  3         9  
1412             }
1413              
1414              
1415             =item lookup key xys
1416              
1417             This returns the value of the key in xys, where xys is a list of key,
1418             value pairs. It returns undef if the key was not found. You should not
1419             do this with infinite lists. Note that this assumes that the keys are
1420             strings. eg:
1421              
1422             $x = lookup(3, [1..6]); # 4
1423              
1424             In Haskell:
1425              
1426             lookup :: Eq a => a -> [(a,b)] -> Maybe b
1427             lookup k [] = Nothing
1428             lookup k ((x,y):xys)
1429             | k==x = Just y
1430             | otherwise = lookup k xys
1431              
1432             TODO: Make sure this works with infinite lists
1433              
1434             =cut
1435              
1436             sub lookup($$) {
1437 1     1 1 509 my($key, $xys) = @_;
1438 1         2 my %hash = @{$xys};
  1         5  
1439 1 50       8 return $hash{$key} if defined $hash{$key};
1440 0         0 return undef;
1441             }
1442              
1443              
1444             =item minimum xs
1445              
1446             Returns the minimum value in xs.
1447             You should not do this with a infinite list.
1448             eg:
1449              
1450             $x = minimum([1..6]); # 1
1451              
1452             In Haskell:
1453              
1454             minimum :: Ord a => [a] -> a
1455             minimum = foldl1 min
1456              
1457             =cut
1458              
1459             sub minimum($) {
1460 1     1 1 3 my $xs = shift;
1461 1         6 return foldl1(\&min, $xs);
1462             }
1463              
1464              
1465             =item maximum xs
1466              
1467             Returns the maximum value in xs.
1468             You should not do this with an infinite list.
1469             eg: maximum([1..6]) = 6. In Haskell:
1470              
1471             maximum :: Ord a => [a] -> a
1472             maximum = foldl1 max
1473              
1474             =cut
1475              
1476             sub maximum($) {
1477 3     3 1 4 my $xs = shift;
1478 3         12 return foldl1(\&max, $xs);
1479             }
1480              
1481              
1482             =item sum xs
1483              
1484             Returns the sum of the elements of xs.
1485             You should not do this with an infinite list.
1486             eg: sum([1..6]) = 21. In Haskell:
1487              
1488             sum :: Num a => [a] -> a
1489             sum = foldl' (+) 0
1490              
1491             =cut #'
1492              
1493             sub sum($) {
1494 1     1 1 1 my $xs = shift;
1495 1     6   6 return foldl(sub { $_[0] + $_[1] }, 0, $xs);
  6         12  
1496             }
1497              
1498              
1499             =item product xs
1500              
1501             Returns the products of the elements of xs.
1502             You should not do this with an infinite list.
1503             eg: product([1..6]) = 720. In Haskell:
1504              
1505             product :: Num a => [a] -> a
1506             product = foldl' (*) 1
1507              
1508             =cut #'
1509              
1510             sub product($) {
1511 1     1 1 2 my $xs = shift;
1512 1     6   7 return foldl(sub { $_[0] * $_[1] }, 1,$xs);
  6         10  
1513             }
1514              
1515              
1516             =item zip as bs
1517              
1518             Zips together two lists into one list. Should
1519             not be done with infinite lists.
1520             eg: zip([1..6], [7..12]) = [1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12].
1521             In Haskell:
1522              
1523             zip :: [a] -> [b] -> [(a,b)]
1524             zip = zipWith (\a b -> (a,b))
1525              
1526             zipWith :: (a->b->c) -> [a]->[b]->[c]
1527             zipWith z (a:as) (b:bs) = z a b : zipWith z as bs
1528             zipWith _ _ _ = []
1529              
1530             =cut
1531              
1532             sub zip($$) {
1533 1     1 1 2 my($as, $bs) = @_;
1534 1         2 my @result;
1535 1         4 foreach (1..max(Length($as), Length($bs))) {
1536 6         6 push @result, shift @{$as};
  6         9  
1537 6         6 push @result, shift @{$bs};
  6         11  
1538             }
1539 1         6 return [@result];
1540             }
1541              
1542              
1543             =item zip3 as bs cs
1544              
1545             Zips together three lists into one. Should not be
1546             done with infinite lists.
1547             eg: zip3([1..2], [3..4], [5..6]) = [1, 3, 5, 2, 4, 6].
1548             In Haskell:
1549              
1550             zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
1551             zip3 = zipWith3 (\a b c -> (a,b,c))
1552              
1553             zipWith3 :: (a->b->c->d) -> [a]->[b]->[c]->[d]
1554             zipWith3 z (a:as) (b:bs) (c:cs)
1555             = z a b c : zipWith3 z as bs cs
1556             zipWith3 _ _ _ _ = []
1557              
1558             =cut
1559              
1560             sub zip3($$$) {
1561 1     1 1 2 my($as, $bs, $cs) = @_;
1562 1         1 my @result;
1563 1         10 foreach (1..maximum([Length($as), Length($bs), Length($cs)])) {
1564 2         3 push @result, shift @{$as};
  2         4  
1565 2         2 push @result, shift @{$bs};
  2         4  
1566 2         3 push @result, shift @{$cs};
  2         4  
1567             }
1568 1         6 return [@result];
1569             }
1570              
1571              
1572             =item unzip abs
1573              
1574             Unzips one list into two. Should not be done with infinite lists.
1575             eg: unzip([1,7,2,8,3,9,4,10,5,11,6,12]) = ([1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]).
1576              
1577             unzip :: [(a,b)] -> ([a],[b])
1578             unzip = foldr (\(a,b) ~(as,bs) -> (a:as, b:bs)) ([], [])
1579              
1580             =cut
1581              
1582             sub unzip($) {
1583 1     1 1 2 my $abs = shift;
1584 1         2 my(@as, @bs);
1585 1         2 while (@{$abs}) {
  7         16  
1586 6         3 push @as, shift @{$abs};
  6         9  
1587 6         6 push @bs, shift @{$abs};
  6         8  
1588             }
1589 1         8 return [@as], [@bs];
1590             }
1591              
1592              
1593             =item unzip abcs
1594              
1595             Unzips one list into three. Should not be done with infinite lists.
1596             eg: unzip3([1,3,5,2,4,6]) = ([1, 2], [3, 4], [5, 6]).
1597             In Haskell:
1598              
1599             unzip3 :: [(a,b,c)] -> ([a],[b],[c])
1600             unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
1601             ([],[],[])
1602              
1603             =cut
1604              
1605             sub unzip3($) {
1606 1     1 0 1 my $abcs = shift;
1607 1         3 my(@as, @bs, @cs);
1608 1         2 while (@{$abcs}) {
  3         8  
1609 2         3 push @as, shift @{$abcs};
  2         4  
1610 2         2 push @bs, shift @{$abcs};
  2         3  
1611 2         3 push @cs, shift @{$abcs};
  2         3  
1612             }
1613 1         9 return [@as], [@bs], [@cs];
1614             }
1615              
1616              
1617             =item integers
1618              
1619             A useful function that returns an infinite list containing
1620             all the integers. eg: integers = (1, 2, 3, 4, 5, ...).
1621              
1622             =cut
1623              
1624             sub integers() {
1625 32871     32871 1 76117 return iterate { shift() +1 } 1;
  26     26   2035  
1626             }
1627              
1628              
1629             =item factors x
1630              
1631             A useful function that returns the factors of x.
1632             eg: factors(100) = [1, 2, 4, 5, 10, 20, 25, 50, 100].
1633             In Haskell:
1634              
1635             factors x = [n | n <- [1..x], x `mod` n == 0]
1636              
1637             =cut
1638              
1639             sub factors($) {
1640 30     30 1 35 my $x = shift;
1641 30         77 return [grep { $x % $_ == 0 } (1..$x)];
  535         716  
1642             }
1643              
1644              
1645             =item prime x
1646              
1647             A useful function that returns, rather unefficiently,
1648             if x is a prime number or not. It is rather useful while
1649             used as a filter,
1650             eg: take(10, filter("prime", integers)) = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29].
1651             In Haskell:
1652              
1653             primes = [n | n <- [2..], length (factors n) == 2]
1654              
1655             =cut
1656              
1657             sub prime($) {
1658 29     29 1 98 my $x = shift;
1659 29         46 return Length(factors($x)) == 2;
1660             }
1661              
1662             =back
1663              
1664             =head1 AUTHOR
1665              
1666             Leon Brocard EFE
1667              
1668             =head1 COPYRIGHT
1669              
1670             Copyright (C) 1999-2008, Leon Brocard
1671              
1672             =head1 LICENSE
1673              
1674             This module is free software; you can redistribute it or modify it
1675             under the same terms as Perl itself.
1676              
1677             =cut
1678              
1679              
1680              
1681              
1682             package InfiniteList;
1683 1     1   8 use strict;
  1         2  
  1         25  
1684 1     1   4 use Carp;
  1         2  
  1         61  
1685 1     1   1144 use Tie::Array;
  1         1184  
  1         28  
1686 1     1   6 use vars qw(@ISA);
  1         2  
  1         431  
1687             @ISA = ('Tie::Array');
1688              
1689             sub TIEARRAY {
1690 52     52   87 my $class = shift;
1691 52         64 my $closure = shift;
1692 52   66     146 my $size = shift || $Language::Functional::INFINITE;
1693 52 50 33     260 confess "usage: tie(\@ary, 'InfiniteList', &closure)"
1694             if @_ || ref($closure) ne 'CODE';
1695 52         320 return bless {
1696             CLOSURE => $closure,
1697             ARRAY => [],
1698             SIZE => $size,
1699             }, $class;
1700             }
1701              
1702             sub FETCH {
1703 82419     82419   113907 my($self,$idx) = @_;
1704 82419         81512 my $debug = 0;
1705 82419 50       147676 print ":fetch $idx... " if $debug;
1706 82419 100 66     308959 if ($idx == $Language::Functional::INFINITE or $idx == $Language::Functional::INFINITE-1) {
1707 6         1376 confess "Fetching an infinite amount of values!";
1708             }
1709 82413 100       156432 if (not defined $self->{ARRAY}[$idx]) {
1710 45308 50       71063 print "MISS\n" if $debug;
1711 45308         90374 $self->{ARRAY}[$idx] = $self->{CLOSURE}->($self, $idx);
1712             } else {
1713 37105 50       63612 print "HIT\n" if $debug;
1714             }
1715 82411 50       167136 print ":so $idx = ", $self->{ARRAY}[$idx], "\n" if $debug;
1716 82411         247016 return $self->{ARRAY}[$idx];
1717             }
1718              
1719             sub FETCHSIZE {
1720 33065     33065   35253 my $self = shift;
1721 33065         133412 return $self->{SIZE};
1722             }
1723              
1724             sub STORE {
1725 3     3   15 my $self = shift;
1726 3         433 confess "Storing, this should never happen to an infinite list!";
1727             }
1728              
1729             sub STORESIZE {
1730 6     6   10 my($self, $size) = @_;
1731 6         11 $self->{SIZE} = $size;
1732             }
1733