Browse code
more transforms
Ed Langley authored on 06/11/2018 08:41:32
Showing 2 changed files
Showing 2 changed files
... | ... |
@@ -2,7 +2,8 @@ |
2 | 2 |
:description "Utilities for building data transormations from composable functions, modeled on lenses and transducers" |
3 | 3 |
:author "Edward Langley <edward@elangley.org>" |
4 | 4 |
:license "MIT" |
5 |
- :depends-on (cl-ppcre) |
|
5 |
+ :depends-on (cl-ppcre |
|
6 |
+ alexandria) |
|
6 | 7 |
:serial t |
7 | 8 |
:components ((:file "lens"))) |
8 | 9 |
|
... | ... |
@@ -8,9 +8,35 @@ |
8 | 8 |
#:extract-key |
9 | 9 |
#:element |
10 | 10 |
#:let-fn |
11 |
- #:juxt)) |
|
11 |
+ #:juxt |
|
12 |
+ #:transform-tail |
|
13 |
+ #:slice |
|
14 |
+ #:compress-runs |
|
15 |
+ #:combine-matching-lists |
|
16 |
+ #:sorted |
|
17 |
+ #:applicable-when |
|
18 |
+ #:of-length |
|
19 |
+ #:of-min-length |
|
20 |
+ #:of-max-length |
|
21 |
+ #:transform-head |
|
22 |
+ #:maximizing |
|
23 |
+ #:zipping)) |
|
12 | 24 |
(in-package :data-lens) |
13 | 25 |
|
26 |
+(declaim |
|
27 |
+ (inline data-lens:over |
|
28 |
+ data-lens:transform-tail |
|
29 |
+ data-lens:applicable-when |
|
30 |
+ data-lens:of-min-length |
|
31 |
+ data-lens:on |
|
32 |
+ data-lens:over |
|
33 |
+ data-lens:slice |
|
34 |
+ data-lens:compress-runs |
|
35 |
+ data-lens:combine-matching-lists |
|
36 |
+ data-lens:juxt |
|
37 |
+ data-lens:element |
|
38 |
+ data-lens:sorted)) |
|
39 |
+ |
|
14 | 40 |
(defmacro shortcut (name function &body bound-args) |
15 | 41 |
`(eval-when (:load-toplevel :compile-toplevel :execute) |
16 | 42 |
(setf (fdefinition ',name) |
... | ... |
@@ -72,6 +98,27 @@ |
72 | 98 |
it |
73 | 99 |
:initial-value ())))) |
74 | 100 |
|
101 |
+(defun-ct of-length (len) |
|
102 |
+ (lambda (it) |
|
103 |
+ (= (length it) |
|
104 |
+ len))) |
|
105 |
+ |
|
106 |
+(defun-ct of-min-length (len) |
|
107 |
+ (lambda (it) |
|
108 |
+ (>= (length it) |
|
109 |
+ len))) |
|
110 |
+ |
|
111 |
+(defun-ct of-max-length (len) |
|
112 |
+ (lambda (it) |
|
113 |
+ (>= (length it) |
|
114 |
+ len))) |
|
115 |
+ |
|
116 |
+(defun-ct applicable-when (fun test) |
|
117 |
+ (lambda (it) |
|
118 |
+ (if (funcall test it) |
|
119 |
+ (funcall fun it) |
|
120 |
+ it))) |
|
121 |
+ |
|
75 | 122 |
(defun-ct sorted (comparator &rest r &key key) |
76 | 123 |
(declare (ignore key)) |
77 | 124 |
(lambda (it) |
... | ... |
@@ -106,6 +153,11 @@ |
106 | 153 |
(lambda (it) |
107 | 154 |
(subseq it start end))) |
108 | 155 |
|
156 |
+(defun-ct transform-head (fun) |
|
157 |
+ (lambda (it) |
|
158 |
+ (list* (funcall fun (car it)) |
|
159 |
+ (cdr it)))) |
|
160 |
+ |
|
109 | 161 |
(defun-ct transform-tail (fun) |
110 | 162 |
(lambda (it) |
111 | 163 |
(list* (car it) |
... | ... |
@@ -117,20 +169,28 @@ |
117 | 169 |
(funcall key-set |
118 | 170 |
(funcall fun key-val))))) |
119 | 171 |
|
120 |
-(defun-ct juxt (fun1 fun2) |
|
121 |
- (lambda (item) |
|
122 |
- (list (funcall fun1 item) |
|
123 |
- (funcall fun2 item)))) |
|
172 |
+(defun-ct juxt (fun1 fun2 &rest r) |
|
173 |
+ (lambda (&rest args) |
|
174 |
+ (list* (apply fun1 args) |
|
175 |
+ (apply fun2 args) |
|
176 |
+ (when r |
|
177 |
+ (mapcar (lambda (f) |
|
178 |
+ (apply f args)) |
|
179 |
+ r))))) |
|
124 | 180 |
|
125 | 181 |
(defun-ct derive (diff-fun &key (key #'identity)) |
126 | 182 |
(lambda (list) |
127 |
- (mapcar (lambda (next cur) |
|
128 |
- (cons (funcall diff-fun (funcall key next) (funcall key cur)) |
|
129 |
- next)) |
|
130 |
- (cdr list) |
|
131 |
- list))) |
|
132 |
- |
|
133 |
-(defun-ct cumsum (&key (add-fun #'+) (key #'identity) (combine (lambda (x y) y x)) (zero 0)) |
|
183 |
+ (cons (cons nil (car list)) |
|
184 |
+ (mapcar (lambda (next cur) |
|
185 |
+ (cons (funcall diff-fun |
|
186 |
+ (funcall key next) |
|
187 |
+ (funcall key cur)) |
|
188 |
+ next)) |
|
189 |
+ (cdr list) |
|
190 |
+ list)))) |
|
191 |
+ |
|
192 |
+(defun-ct cumsum |
|
193 |
+ (&key (add-fun #'+) (key #'identity) (combine (lambda (x y) y x)) (zero 0)) |
|
134 | 194 |
(lambda (seq) |
135 | 195 |
(nreverse |
136 | 196 |
(reduce (lambda (accum next) |
... | ... |
@@ -152,3 +212,41 @@ |
152 | 212 |
(defun-ct on (fun key) |
153 | 213 |
(lambda (it) |
154 | 214 |
(funcall fun (funcall key it)))) |
215 |
+ |
|
216 |
+(defun filler (length1 length2 fill-value) |
|
217 |
+ (if (< length1 length2) |
|
218 |
+ (make-sequence 'vector (- length2 length1) :initial-element fill-value) |
|
219 |
+ #())) |
|
220 |
+ |
|
221 |
+(defun-ct zipping (result-type &key (fill-value nil fill-value-p)) |
|
222 |
+ (lambda (seq1 seq2) |
|
223 |
+ (let ((length1 (when fill-value-p (length seq1))) |
|
224 |
+ (length2 (when fill-value-p (length seq2)))) |
|
225 |
+ (let ((seq1 (if fill-value-p |
|
226 |
+ (concatenate result-type |
|
227 |
+ seq1 |
|
228 |
+ (filler length1 length2 fill-value)) |
|
229 |
+ seq1)) |
|
230 |
+ (seq2 (if fill-value-p |
|
231 |
+ (concatenate result-type |
|
232 |
+ seq2 |
|
233 |
+ (filler length2 length1 fill-value)) |
|
234 |
+ seq2))) |
|
235 |
+ (map result-type #'list |
|
236 |
+ seq1 seq2))))) |
|
237 |
+ |
|
238 |
+(defun-ct maximizing (relation measure) |
|
239 |
+ (lambda (it) |
|
240 |
+ (let ((it-length (length it))) |
|
241 |
+ (when (> it-length 0) |
|
242 |
+ (values-list |
|
243 |
+ (reduce (fw.lu:destructuring-lambda ((cur-max max-idx) |
|
244 |
+ (next next-idx)) |
|
245 |
+ (if (funcall relation |
|
246 |
+ (funcall measure cur-max) |
|
247 |
+ (funcall measure next)) |
|
248 |
+ (list next next-idx) |
|
249 |
+ (list cur-max max-idx))) |
|
250 |
+ (funcall (zipping 'vector) |
|
251 |
+ it |
|
252 |
+ (alexandria:iota it-length)))))))) |