Compare commits

...

4 Commits

9 changed files with 172 additions and 23 deletions

View File

@ -73,4 +73,4 @@ jobs:
--eval "(handler-case (ql:quickload :data-lens/test) (error (c) (format t \"~a\" c) (uiop:quit 44)))" \
--eval "(handler-case (asdf:test-system :data-lens) (error (c) (format t \"~a\" c) (uiop:quit 45)))" \
--eval "(handler-case (asdf:test-system :data-lens/transducers) (error (c) (format t \"~a\" c) (uiop:quit 46)))" \
--quit
--quit 2>&1 | grep -v '^;'

11
data-lens+fset.asd Normal file
View File

@ -0,0 +1,11 @@
(in-package :asdf-user)
(asdf:defsystem #:data-lens+fset
:author "Edward Langley <el-cl@elangley.org>"
:license "Apache v2"
:depends-on (:data-lens
:data-lens/transducers
:fset)
:serial t
:in-order-to ((test-op (test-op :data-lens/test)))
:components ((:file "data-lens-fset")))

110
data-lens-fset.lisp Normal file
View File

@ -0,0 +1,110 @@
(defpackage :fwoar.data-lens-fset
(:use :cl )
(:export
#:make-seq-lens
#:make-bag-lens
#:make-set-lens))
(in-package :fwoar.data-lens-fset)
(named-readtables:in-readtable fset:fset-readtable)
(defmethod data-lens.transducers.internals:reduce-generic ((set fset:set) (func function) init)
(fset:reduce func set :initial-value init))
(defmethod data-lens.transducers.internals:builder-for-input ((seq fset:set))
(values 'fset-set-builder
seq))
(defmethod data-lens.transducers.internals:stepper ((seq (eql 'fset-set-builder)))
(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:extract-key ((it fset:set) key)
(nth-value 1 (fset:lookup it key)))
(defun make-set-lens (item)
"A lens for updating a set"
(lambda (cb)
(lambda (set)
(data-lens.lenses:fmap (lambda (new)
(fset:with (fset:less set item) new))
(funcall cb (nth-value 1 (fset:lookup set item)))))))
(defmethod data-lens.lenses:generic-lens ((rec fset:set) cb loc)
(funcall (funcall (make-set-lens loc)
cb)
rec))
(defmethod data-lens.transducers.internals:reduce-generic ((seq fset:seq) (func function) init)
(fset:reduce func seq :initial-value init))
(defmethod data-lens.transducers.internals:builder-for-input ((seq fset:seq))
(values 'fset-seq-builder
seq))
(defmethod data-lens.transducers.internals:stepper ((seq (eql 'fset-seq-builder)))
(data-lens.transducers:transducer-lambda
((acc next)
(fset:with-last acc next))))
(defmethod data-lens:functionalize ((it fset:seq))
(lambda (key)
(fset:lookup it key)))
(defmethod data-lens:extract-key ((it fset:seq) key)
(fset:lookup it key))
(defmethod data-lens.lenses:fmap (function (data fset:seq)))
(defun make-seq-lens (index)
"A lens for updating a sequence"
(check-type index (integer 0))
(lambda (cb)
(lambda (seq)
(data-lens.lenses:fmap (lambda (new)
(fset:with seq index new))
(funcall cb (fset:lookup seq index))))))
(defmethod data-lens.lenses:generic-lens ((rec fset:seq) cb (loc integer))
(funcall (funcall (make-seq-lens loc)
cb)
rec))
(defmethod data-lens.transducers.internals:builder-for-input ((map fset:map))
(values 'fset-map-builder
map))
(defmethod data-lens.transducers.internals:stepper ((map (eql 'fset-map-builder)))
(data-lens.transducers:transducer-lambda
((acc next)
(destructuring-bind (k v) next
(fset:with acc k v)))))
(defmethod data-lens:functionalize ((it fset:map))
(lambda (key)
(fset:lookup it key)))
(defmethod data-lens:extract-key ((it fset:map) key)
(fset:lookup it key))
(defun make-map-lens (key)
(lambda (cb)
(lambda (map)
(data-lens.lenses:fmap (lambda (new)
(fset:with map key new))
(funcall cb (fset:lookup map key))))))
(defmethod data-lens.lenses:generic-lens ((rec fset:map) cb loc)
(funcall (funcall (make-map-lens loc)
cb)
rec))
(defmethod data-lens.transducers.internals:builder-for-input ((bag fset:bag))
(values 'fset-bag-builder
bag))
(defmethod data-lens.transducers.internals:stepper ((bag (eql 'fset-bag-builder)))
(data-lens.transducers:transducer-lambda
((acc next)
(fset:with acc next))))
(defmethod data-lens:functionalize ((it fset:bag))
(lambda (key)
(fset:multiplicity it key)))
(defmethod data-lens:extract-key ((it fset:bag) key)
(let ((m (fset:multiplicity it key)))
(values key
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

@ -8,9 +8,7 @@
:author "Edward Langley <el-cl@elangley.org>"
:license "Apache v2"
:depends-on (:cl-ppcre
:alexandria
#+(or)
(:require :sb-cover))
:alexandria)
:serial t
:in-order-to ((test-op (test-op :data-lens/test)))
:components ((:file "package")
@ -23,8 +21,7 @@
:license "Apache v2"
:depends-on (:data-lens
:fiveam
:string-case
:serapeum)
:string-case)
:serial t
:perform (test-op (o c)
(unless (symbol-call :fiveam '#:run! :data-lens.lens)
@ -38,8 +35,7 @@
:author "Edward Langley <el-cl@elangley.org>"
:license "Apache v2"
:depends-on (:data-lens
:alexandria
:serapeum)
:alexandria)
:serial t
:in-order-to ((test-op (test-op :data-lens/transducers/test)))
:components ((:file "package")

View File

@ -29,6 +29,11 @@
(lambda ()
v))))
(defun unsplice (form)
(if form
(list form)
nil))
(defun iota (&key (start 0) (step 1) count)
(lazy-sequence
(funcall
@ -36,14 +41,14 @@
`(lambda ()
(declare (optimize (speed 3) (debug 1) (safety 1)))
(let ((init ,start)
,@(serapeum:unsplice (when count
,@(unsplice (when count
'(iterations 0))))
(declare (type (integer ,start
,(if count
(+ start (* count step))
'*))
init)
,@(serapeum:unsplice
,@(unsplice
(when count
`(type (integer 0 ,count) iterations))))
(lambda ()
@ -53,6 +58,6 @@
'(progn))
(prog1 init
(incf init ,step)
,@(serapeum:unsplice
,@(unsplice
(when count
'(incf iterations))))))))))))

View File

@ -7,7 +7,10 @@
(:shadow :set)
(:use :cl)
(:export #:over #:set #:view #:make-alist-lens #:make-plist-lens
#:make-hash-table-lens #:make-list-lens))
#:make-hash-table-lens #:make-list-lens
#:make-lens
#:generic-lens
#:fmap))
(defpackage :data-lens
(:use :cl)
@ -21,7 +24,8 @@
#:transform-elt #:denest #:op #:defalias #:<> #:<>1 #:== #:
#: #:suffixp #:functionalize #:inc #:group-by #:keys
#:conj #:disj #:delay #:of-type #:transform #:calling*
#:calling #:hash-join #:tap #:x-group))
#:calling
#:closing))
(defpackage :data-lens.transducers.internals
(:use :cl)
@ -38,4 +42,5 @@
#:hash-table-builder #:vector-builder #:list-builder
#:collecting #:mv-mapping #:mv-selecting #:hash-table-select
#:mv-filtering #:mapcatting #:lazy-sequence
#:compressing-runs #:iota #:repeating #:repeating* #:into))
#:compressing-runs #:iota #:repeating #:repeating* #:into
#:transducer-lambda))

View File

@ -183,9 +183,19 @@
(acons "c" (make-instance 'my-map) ())
:test 'equal))))))))
(defun eqq (a b)
(typecase a
(string (equal a b))
(vector (and (vectorp b)
(= (length a) (length b))
(every 'eqq a b)))
(cons (and (consp b)
(eqq (car a) (car b))
(eqq (cdr a) (cdr b))))
(t (eql a b))))
(5am:def-test regex-match (:suite :data-lens.lens)
(5am:is (serapeum:seq=
(list "acb" #("c"))
(5am:is (eqq (list "acb" #("c"))
(multiple-value-list
(funcall (data-lens:regex-match "a(.)b")
"<acb>")))))

View File

@ -1,6 +1,6 @@
(defpackage :data-lens.t.transducers
(:use :cl )
(:export ))
(:use :cl)
(:export))
(in-package :data-lens.t.transducers)
(5am:def-suite :data-lens.transducers)
@ -182,7 +182,8 @@
(data-lens.transducers:catting)
(data-lens.transducers:mapping #'parse-integer)
(data-lens.transducers:filtering (complement #'evenp))
(data-lens.transducers:splitting (serapeum:op (* 2 _)) #'identity)
(data-lens.transducers:splitting (lambda (_) (* 2 _))
#'identity)
(data-lens.transducers:mapping (data-lens:transform-head #'1+))
(data-lens.transducers:taking 3))
'data-lens.transducers:hash-table-builder

View File

@ -22,6 +22,17 @@
(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))))
(alexandria:with-gensyms (arg1 arg2 next-sym-p)
`(lambda (,arg1 &optional (,arg2 nil ,next-sym-p))
(if ,next-sym-p
(let ((,two-arg-acc ,arg1)
(,two-arg-next ,arg2))
,@two-arg-body)
(let ((,one-arg-arg ,arg1))
,@one-arg-body)))))
(defgeneric unwrap (client obj)
(:method (client obj) obj))
(defgeneric builder-for-input (seq)