git.fiddlerwoaroof.com
Browse code

Reorder lens package

Ed Langley authored on 29/04/2019 07:17:45
Showing 1 changed files
... ...
@@ -4,30 +4,6 @@
4 4
   (:export :over :set :view :make-alist-lens :make-plist-lens :make-hash-table-lens))
5 5
 (in-package :data-lens.lenses)
6 6
 
7
-(defun make-alist-lens (key)
8
-  (lambda (cb)
9
-    (lambda (alist)
10
-      (let ((old-value (serapeum:assocdr key alist)))
11
-        (cons (cons key (funcall cb old-value))
12
-              alist)))))
13
-
14
-(defun make-plist-lens (key)
15
-  (lambda (cb)
16
-    (lambda (plist)
17
-      (let ((old-value (getf plist key)))
18
-        (list* key (funcall cb old-value)
19
-               plist)))))
20
-
21
-(defun make-hash-table-lens (key)
22
-  (lambda (cb)
23
-    (lambda (old-hash)
24
-      (let ((old-value (gethash key old-hash)))
25
-        (fw.lu:prog1-bind (new-hash (alexandria:copy-hash-table old-hash))
26
-          (setf (gethash key new-hash)
27
-                (funcall cb old-value)))))))
28
-
29
-;; imagine a lens here that uses the MOP to immutably update a class...
30
-
31 7
 (defun over (lens cb rec)
32 8
   "Given a lens, a callback and a record, apply the lens to the
33 9
 record, transform it by the callback and return copy of the record,
... ...
@@ -73,6 +49,52 @@ contain the new value at the location focused by the lens."
73 49
             value))
74 50
         rec))
75 51
 
52
+(defun make-alist-lens (key)
53
+  (lambda (cb)
54
+    (lambda (alist)
55
+      (let ((old-value (serapeum:assocdr key alist)))
56
+        (cons (cons key (funcall cb old-value))
57
+              alist)))))
58
+
59
+(defun make-plist-lens (key)
60
+  (lambda (cb)
61
+    (lambda (plist)
62
+      (let ((old-value (getf plist key)))
63
+        (list* key (funcall cb old-value)
64
+               plist)))))
65
+
66
+(defun make-hash-table-lens (key)
67
+  (lambda (cb)
68
+    (lambda (old-hash)
69
+      (let ((old-value (gethash key old-hash)))
70
+        (fw.lu:prog1-bind (new-hash (alexandria:copy-hash-table old-hash))
71
+          (setf (gethash key new-hash)
72
+                (funcall cb old-value)))))))
73
+
74
+;; imagine a lens here that uses the MOP to immutably update a class...
75
+(defgeneric clone (obj &rest new-initargs &key)
76
+  (:method :around (obj &rest new-initargs &key)
77
+    (apply #'reinitialize-instance (call-next-method) new-initargs)))
78
+
79
+#+fw.demo
80
+(progn
81
+  (defclass foo ()
82
+    ((a :initarg :a :accessor a)))
83
+  (defmethod clone ((obj foo) &key)
84
+    (make-instance 'foo :a (a obj)))
85
+
86
+  (defun a-lens (cb)
87
+    (lambda (foo)
88
+      (fw.lu:prog1-bind (new (clone foo))
89
+        (setf (a new)
90
+              (funcall cb (a foo))))))
91
+  (view 'a-lens
92
+        (over 'a-lens '1+
93
+              (set 'a-lens 2
94
+                   (make-instance 'foo :a 1)))) #|
95
+  ==> 3 |#)
96
+
97
+
76 98
 
77 99
 (defpackage :data-lens
78 100
   (:use :cl)
... ...
@@ -82,8 +104,8 @@ contain the new value at the location focused by the lens."
82 104
            #:extract-key #:element #:let-fn #:juxt #:transform-tail #:slice
83 105
            #:compress-runs #:combine-matching-lists #:sorted #:applicable-when
84 106
            #:of-length #:of-min-length #:of-max-length #:transform-head
85
-           #:maximizing #:zipping #:applying #:transform-elt #:denest #:op
86
-           #:defalias #:<> #:<>1))
107
+           #:maximizing #:zipping #:applying #:splice-elt #:transform-elt #:denest
108
+           #:op #:defalias #:<> #:<>1))
87 109
 (in-package :data-lens)
88 110
 
89 111
 
... ...
@@ -236,12 +258,18 @@ contain the new value at the location focused by the lens."
236 258
                   (updatef (subseq result 1)
237 259
                            fun)))))))
238 260
 
239
-(defun-ct transform-elt (elt fun)
261
+(defun-ct splice-elt (elt fun)
240 262
   (lambda (it)
241 263
     (append (subseq it 0 elt)
242 264
             (funcall fun (nth elt it))
243 265
             (subseq it (1+ elt)))))
244 266
 
267
+(defun-ct transform-elt (elt fun)
268
+  (lambda (it)
269
+    (append (subseq it 0 elt)
270
+            (list (funcall fun (nth elt it)))
271
+            (subseq it (1+ elt)))))
272
+
245 273
 (defun-ct key-transform (fun key-get key-set)
246 274
   (lambda (it)
247 275
     (let ((key-val (funcall key-get it)))