forked from fredokun/lisp-lazy-seq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxform.lisp
128 lines (98 loc) · 2.83 KB
/
xform.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
(in-package #:lazyseq)
(defun map1 (f s)
"Maps the (unary) function F over sequence S."
(when s
(lazy-seq (cons (funcall f (head s))
(map1 f (tail s))))))
(example
(take 5 (map1 (lambda (x) (* x x)) (range)))
=> '(0 1 4 9 16))
(defun map2 (f s1 s2)
"Maps the (binary) function F over sequences S1 and S2."
(when (and s1 s2)
(lazy-seq (cons (funcall f (head s1) (head s2))
(map2 f (tail s1) (tail s2))))))
(example
(take 5 (map2 #'* (range) (repeat 2)))
=> '(0 2 4 6 8))
(defun mapn (f &rest seqs)
"Maps the (n-ary) function F over the sequences SEQS."
(when (every (lambda (s) s) seqs)
(lazy-seq (cons (apply f (mapcar #'head seqs))
(apply #'mapn (cons f (mapcar #'tail seqs)))))))
(example
(take 5 (mapn (lambda (x) (* x x)) (range)))
=> '(0 1 4 9 16))
(example
(take 5 (mapn #'* (range) (repeat 2)))
=> '(0 2 4 6 8))
(example
(take 5 (mapn (lambda (x y z u) (+ x y z u))
(range)
(range 10)
(range 100)
(range 1000)))
=> '(1110 1114 1118 1122 1126))
(defun maps (f s &rest seqs)
"Maps the function F over the sequences S (and SEQS)."
(if seqs
(if (rest seqs)
(apply #'mapn f (cons s seqs))
(map2 f s (first seqs)))
(map1 f s)))
(example
(take 5 (maps (lambda (x) (* x x)) (range)))
=> '(0 1 4 9 16))
(example
(take 5 (maps #'* (range) (repeat 2)))
=> '(0 2 4 6 8))
(example
(take 5 (maps (lambda (x y z u) (+ x y z u))
(range)
(range 10)
(range 100)
(range 1000)))
=> '(1110 1114 1118 1122 1126))
(defun filters (pred s)
"Filters sequence S for predicate PRED."
(when s
(if (funcall pred (head s))
(lazy-seq (cons (head s) (filters pred (tail s))))
(filters pred (tail s)))))
(example
(take 5 (filters #'evenp (range)))
=> '(0 2 4 6 8))
(example
(take 5 (filters #'oddp (range)))
=> '(1 3 5 7 9))
(defun scanl (f a s)
"Applies binary function F to A and the first element of the sequence S
then to this result and the second element, and so on.
Returns a lazy sequence [A (F A S[0]) (F (F A S[0]) S[1]) ...]"
(if s
(lazy-seq (cons a (scanl f (funcall f a (head s)) (tail s))))
(list a)))
(example
(take 10 (scanl #'+ 1 '(1 2 3)))
=> '(1 2 4 7))
(defun zip (s &rest seqs)
"Makes a sequence of lists, each containing the element
from the input sequence at the same position.
This can operate on infinite (lazy) sequences
Examples:
(zip (range) '(1 2 3)) => ((0 1) (1 2) (2 3))
(zip (range) \"hello\")
=> ((0 #\h) (1 #\e) (2 #\l) (3 #\l) (4 #\o))
(take 5 (zip (range) (range 2)))
=> ((0 2) (1 3) (2 4) (3 5) (4 6))
"
(apply #'maps #'list s seqs))
(example
(zip (range) '(1 2 3))
=> '((0 1) (1 2) (2 3)))
(example
(zip (range) \"hello\")
=> '((0 #\h) (1 #\e) (2 #\l) (3 #\l) (4 #\o)))
(example
(take 5 (zip (range) (range 2)))
=> '((0 2) (1 3) (2 4) (3 5) (4 6)))