Compare commits

...

6 Commits

5 changed files with 84 additions and 14 deletions

View File

@ -17,9 +17,9 @@
(data-lens.transducers:transducer-lambda
((acc next)
(fset:with acc next))))
(defmethod data-lens:functionalize ((it fset:set))
(lambda (key)
(nth-value 1 (fset:lookup it key))))
(defmethod data-lens:functionalize ((set fset:set))
(lambda (it)
(fset:contains? set it)))
(defmethod data-lens:extract-key ((it fset:set) key)
(nth-value 1 (fset:lookup it key)))
(defun make-set-lens (item)
@ -63,6 +63,11 @@
rec))
(defmethod data-lens.transducers.internals:reduce-generic ((map fset:map) (func function) init)
(fset:reduce (lambda (acc k v)
(funcall func acc (list k v)))
map
:initial-value init))
(defmethod data-lens.transducers.internals:builder-for-input ((map fset:map))
(values 'fset-map-builder
map))
@ -104,7 +109,9 @@
m)))
(defun make-bag-lens (item)
(make-set-lens item))
(defmethod data-lens.lenses:generic-lens ((rec fset:bag) cb loc)
(funcall (funcall (make-set-lens loc)
cb)
rec))

View File

@ -217,3 +217,19 @@ contain the new value at the location focused by the lens."
(set 'a-lens 2
(make-instance 'foo :a 1)))) #|
==> 3 |#)
(defgeneric generic-lens (rec cb loc)
(:method ((rec hash-table) cb loc)
(funcall (funcall (make-hash-table-lens loc)
cb)
rec))
(:method ((rec vector) cb loc)
(funcall (funcall (make-list-lens loc)
cb)
rec)))
(defun lens (loc)
"extensible lens using a multimethod for internal implementation"
(lambda (cb)
(lambda (rec)
(generic-lens rec cb loc))))

View File

@ -237,6 +237,22 @@
'<
:key 'car))))
(5am:is (equalp #(1 2 3 4)
(data-lens.transducers:into #() '(1 2 3 4)))
"~s can be used to convert one type into another without a transducer"
'data-lens.transducers:into)
(5am:is (equalp #(1 2 4)
(handler-bind ((simple-error #'continue))
(data-lens.transducers:into #()
(data-lens.transducers:mapping
(lambda (it)
(if (= it 3)
(error "fail")
it)))
'(1 2 3 4))))
"transducers provide a continue restart")
(loop for type in '(vector list)
do (5am:is (equalp #(1 2 3 4 5 6)
(data-lens.transducers:into #(1 2 3)

View File

@ -16,12 +16,6 @@
seq)
acc)))
#+(or)
(defun document (&rest strings)
(serapeum:string-join strings #.(format nil "~2%")))
(defgeneric init (client))
(defgeneric stepper (client))
(defmacro transducer-lambda (&body (((two-arg-acc two-arg-next) &body two-arg-body)
&optional (((one-arg-arg) &body one-arg-body)
'((it) it))))
@ -33,16 +27,39 @@
,@two-arg-body)
(let ((,one-arg-arg ,arg1))
,@one-arg-body)))))
(defgeneric init (client)
(:method ((client symbol))
(unless (fboundp client)
(error "client not funcallable"))
(init (fdefinition client)))
(:method ((client function))
(funcall client)))
(defgeneric stepper (client)
(:method ((client function))
(transducer-lambda
((acc a)
(declare (optimize (speed 3)))
(funcall client acc a))))
(:method ((client symbol))
(unless (fboundp client)
(error "client not funcallable"))
(init (fdefinition client))))
(defgeneric unwrap (client obj)
(:method (client obj) obj))
(defgeneric builder-for-input (seq)
(:documentation
"Take a transducible sequence, return a builder and an init value for that builder.
CONSTRAINT: SEQ should be copied, not modified"))
(declaim (inline exit-early))
(defun exit-early (acc)
(throw 'done acc))
(declaim (notinline exit-early))
(defun transduce (xf build seq)
(let* ((xf (etypecase xf
@ -56,7 +73,16 @@ CONSTRAINT: SEQ should be copied, not modified"))
transducer
(init build)))))))
(defun into (to xf from)
(defun into (to xf &optional (from nil from-p))
(if (not from-p)
(let ((from xf))
(data-lens.transducers:into to
(data-lens.transducers:mapping
(lambda (&rest args)
(if (null (cdr args))
(car args)
args)))
from))
(multiple-value-bind (builder init) (builder-for-input to)
(let* ((xf (etypecase xf
(list (apply 'alexandria:compose xf))
@ -67,7 +93,7 @@ CONSTRAINT: SEQ should be copied, not modified"))
(catch 'done
(reduce-generic from
transducer
init)))))))
init))))))))
(defmacro defdocumentation (name &body doc-specs)
name doc-specs

View File

@ -23,7 +23,12 @@
(lambda (rf)
(transducer-lambda
((acc next)
(funcall rf acc (call-function next)))
(restart-case
(funcall rf acc (call-function next))
(continue ()
:report (lambda (s)
(format s "skip this item"))
acc)))
((it) (funcall rf it))))))
(defun mv-mapping (function &rest args)