git.fiddlerwoaroof.com
Browse code

more transforms

Ed Langley authored on 06/11/2018 08:41:32
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))))))))