git.fiddlerwoaroof.com
Browse code

feat: allow over to accept multiple functions and compose them

Edward Langley authored on 13/04/2023 16:29:22
Showing 2 changed files
... ...
@@ -291,10 +291,29 @@
291 291
              seq
292 292
              :initial-value ()))))
293 293
 
294
-(defun over (fun &key (result-type 'list))
295
-  (let ((fun (functionalize fun)))
296
-    (lambda (seq)
297
-      (map result-type fun seq))))
294
+(defun over (fun &rest funs)
295
+  (let* ((fun (functionalize fun))
296
+         (rt-pos (position :result-type funs))
297
+         (result-type (cond
298
+                        ((null rt-pos) 'list)
299
+                        ((>= (1+ rt-pos)
300
+                             (length funs))
301
+                         (error "invalid result-type"))
302
+                        (t
303
+                         (elt funs (1+ rt-pos)))))
304
+         (funs (if rt-pos
305
+                   (append (mapcar #'functionalize
306
+                                   (subseq funs 0 rt-pos))
307
+                           (mapcar #'functionalize
308
+                                   (subseq funs (+ rt-pos 2))))
309
+                   (mapcar #'functionalize funs)))
310
+         (combined-fun (if funs
311
+                           (apply #'alexandria:compose fun funs)
312
+                           fun)))
313
+    (lambda (seq &rest seqs)
314
+      (if seqs
315
+          (apply #'map result-type combined-fun seq seqs)
316
+          (map result-type combined-fun seq)))))
298 317
 
299 318
 (defun denest (&key (result-type 'list))
300 319
   (lambda (seq)
... ...
@@ -250,6 +250,12 @@
250 250
   (5am:is (equalp #(1 2 3)
251 251
                   (funcall (data-lens:over '1+ :result-type 'vector)
252 252
                            '(0 1 2))))
253
+  (5am:is (equalp #(2 3 4)
254
+                  (funcall (data-lens:over '1+ :result-type 'vector '1+)
255
+                           '(0 1 2))))
256
+  (5am:is (equalp #(2 3 4)
257
+                  (funcall (data-lens:over '1+ '1+ :result-type 'vector)
258
+                           '(0 1 2))))
253 259
   (5am:is (equalp #(1 2 3)
254 260
                   (funcall (data-lens:over '1+ :result-type 'vector)
255 261
                            #(0 1 2)))))