Compare commits

..

6 Commits

3 changed files with 63 additions and 36 deletions

View File

@ -24,6 +24,16 @@
(:method ((it function)) (:method ((it function))
it)) it))
(define-compiler-macro functionalize (&whole whole it)
(typecase it
(cons (destructuring-bind (h . tail) it
(declare (ignore tail))
(case h
(quote it)
(function it)
(t whole))))
(t whole)))
;;; TODO: consider making this wrap defalias? ;;; TODO: consider making this wrap defalias?
(defmacro shortcut (name function &body bound-args) (defmacro shortcut (name function &body bound-args)
`(eval-when (:load-toplevel :compile-toplevel :execute) `(eval-when (:load-toplevel :compile-toplevel :execute)
@ -53,11 +63,11 @@
when (equal key a-key) do when (equal key a-key) do
(return (car value))))))) (return (car value)))))))
(defun-ct == (target &key (test 'eql)) (defun == (target &key (test 'eql))
(lambda (v) (lambda (v)
(funcall test target v))) (funcall test target v)))
(defun-ct deduplicate (&optional (test 'eql)) (defun deduplicate (&optional (test 'eql))
(lambda (it) (lambda (it)
(remove-duplicates it :test test))) (remove-duplicates it :test test)))
@ -83,29 +93,29 @@
(lambda (acc next) (lambda (acc next)
(matching-list-reducer test acc next))) (matching-list-reducer test acc next)))
(defun-ct compress-runs (&key (collector 'cons-new) (test 'eql) (key 'identity)) (defun compress-runs (&key (collector 'cons-new) (test 'eql) (key 'identity))
(lambda (it) (lambda (it)
(nreverse (nreverse
(reduce (funcall collector :test test :key key) (reduce (funcall collector :test test :key key)
it it
:initial-value ())))) :initial-value ()))))
(defun-ct of-length (len) (defun of-length (len)
(lambda (it) (lambda (it)
(= (length it) (= (length it)
len))) len)))
(defun-ct of-min-length (len) (defun of-min-length (len)
(lambda (it) (lambda (it)
(>= (length it) (>= (length it)
len))) len)))
(defun-ct of-max-length (len) (defun of-max-length (len)
(lambda (it) (lambda (it)
(<= (length it) (<= (length it)
len))) len)))
(defun-ct applicable-when (fun test) (defun applicable-when (fun test)
(lambda (it) (lambda (it)
(if (funcall test it) (if (funcall test it)
(funcall fun it) (funcall fun it)
@ -127,16 +137,16 @@
fns))))) fns)))))
(defun-ct sorted (comparator &rest r &key key) (defun sorted (comparator &rest r &key key)
(declare (ignore key)) (declare (ignore key))
(lambda (it) (lambda (it)
(apply #'stable-sort (copy-seq it) comparator r))) (apply #'stable-sort (copy-seq it) comparator r)))
(defun-ct element (num) (defun element (num)
(lambda (it) (lambda (it)
(elt it num))) (elt it num)))
(defun-ct key (key) (defun key (key)
(lambda (map) (lambda (map)
(declare (dynamic-extent map)) (declare (dynamic-extent map))
(extract-key map key))) (extract-key map key)))
@ -147,19 +157,19 @@
for cur = (extract-key map key) then (extract-key cur key) for cur = (extract-key map key) then (extract-key cur key)
finally (return cur)))) finally (return cur))))
(defun-ct regex-match (regex) (defun regex-match (regex)
(lambda (data) (lambda (data)
(cl-ppcre:scan-to-strings regex data))) (cl-ppcre:scan-to-strings regex data)))
(defun-ct include (pred) (defun include (pred)
(lambda (seq) (lambda (seq)
(remove-if-not pred seq))) (remove-if-not pred seq)))
(defun-ct exclude (pred) (defun exclude (pred)
(lambda (seq) (lambda (seq)
(remove-if pred seq))) (remove-if pred seq)))
(defun-ct pick (selector) (defun pick (selector)
(lambda (seq) (lambda (seq)
(map 'list selector seq))) (map 'list selector seq)))
@ -167,13 +177,13 @@
(lambda (it) (lambda (it)
(subseq it start end))) (subseq it start end)))
(defun-ct update (thing fun &rest args) (defun update (thing fun &rest args)
(apply fun thing args)) (apply fun thing args))
(define-modify-macro updatef (fun &rest args) (define-modify-macro updatef (fun &rest args)
update) update)
(defun-ct suffixp (suffix &key (test 'eql test-p)) (defun suffixp (suffix &key (test 'eql test-p))
(lambda (it) (lambda (it)
(if test-p (if test-p
(alexandria:ends-with-subseq suffix (alexandria:ends-with-subseq suffix
@ -182,7 +192,7 @@
(alexandria:ends-with-subseq suffix (alexandria:ends-with-subseq suffix
it)))) it))))
(defun-ct transform-head (fun) (defun transform-head (fun)
(lambda (it) (lambda (it)
(typecase it (typecase it
(list (list* (funcall fun (car it)) (list (list* (funcall fun (car it))
@ -191,7 +201,7 @@
(prog1 result (prog1 result
(updatef (elt result 0) fun))))))) (updatef (elt result 0) fun)))))))
(defun-ct transform-tail (fun) (defun transform-tail (fun)
(lambda (it) (lambda (it)
(typecase it (typecase it
(list (list* (car it) (list (list* (car it)
@ -201,25 +211,25 @@
(updatef (subseq result 1) (updatef (subseq result 1)
fun))))))) fun)))))))
(defun-ct splice-elt (elt fun) (defun splice-elt (elt fun)
(lambda (it) (lambda (it)
(append (subseq it 0 elt) (append (subseq it 0 elt)
(funcall fun (nth elt it)) (funcall fun (nth elt it))
(subseq it (1+ elt))))) (subseq it (1+ elt)))))
(defun-ct transform-elt (elt fun) (defun transform-elt (elt fun)
(lambda (it) (lambda (it)
(append (subseq it 0 elt) (append (subseq it 0 elt)
(list (funcall fun (nth elt it))) (list (funcall fun (nth elt it)))
(subseq it (1+ elt))))) (subseq it (1+ elt)))))
(defun-ct key-transform (fun key-get key-set) (defun key-transform (fun key-get key-set)
(lambda (it) (lambda (it)
(let ((key-val (funcall key-get it))) (let ((key-val (funcall key-get it)))
(funcall key-set (funcall key-set
(funcall fun key-val))))) (funcall fun key-val)))))
(defun-ct juxt (fun1 &rest r) (defun juxt (fun1 &rest r)
(lambda (&rest args) (lambda (&rest args)
(list* (apply fun1 args) (list* (apply fun1 args)
(when r (when r
@ -239,7 +249,7 @@
(prog1 (funcall fun1 i) (prog1 (funcall fun1 i)
(funcall fun2)))) (funcall fun2))))
(defun-ct derive (diff-fun &key (key #'identity)) (defun derive (diff-fun &key (key #'identity))
(lambda (seq) (lambda (seq)
(typecase seq (typecase seq
(list (cons (cons nil (car seq)) (list (cons (cons nil (car seq))
@ -260,12 +270,12 @@
else collect (cons nil next)) else collect (cons nil next))
'vector))))) 'vector)))))
(defun-ct inc (inc) (defun inc (inc)
(declare (optimize (speed 3))) (declare (optimize (speed 3)))
(lambda (base) (lambda (base)
(+ base inc))) (+ base inc)))
(defun-ct cumsum (defun cumsum
(&key (add-fun #'+) (key #'identity) (combine (lambda (x y) y x)) (zero 0)) (&key (add-fun #'+) (key #'identity) (combine (lambda (x y) y x)) (zero 0))
(lambda (seq) (lambda (seq)
(nreverse (nreverse
@ -281,23 +291,28 @@
seq seq
:initial-value ())))) :initial-value ()))))
(defun-ct over (fun &key (result-type 'list)) (defun over (fun &key (result-type 'list))
(let ((fun (functionalize fun))) (let ((fun (functionalize fun)))
(lambda (seq) (lambda (seq)
(map result-type fun seq)))) (map result-type fun seq))))
(defun-ct denest (&key (result-type 'list)) (defun denest (&key (result-type 'list))
(lambda (seq) (lambda (seq)
(apply #'concatenate result-type (apply #'concatenate result-type
seq))) seq)))
(defmacro calling (fun &rest args)
(alexandria:with-gensyms (first-arg)
`(lambda (,first-arg)
(funcall (functionalize ,fun) ,first-arg ,@args))))
(defmacro applying (fun &rest args) (defmacro applying (fun &rest args)
(alexandria:with-gensyms (seq fsym) (alexandria:with-gensyms (seq fsym)
`(let ((,fsym (functionalize ,fun))) `(let ((,fsym (functionalize ,fun)))
(lambda (,seq) (lambda (,seq)
(apply ,fsym ,@args ,seq))))) (apply ,fsym ,@args ,seq)))))
(defun-ct on (fun key) (defun on (fun key)
"Transform arguments with KEY and then apply FUN "Transform arguments with KEY and then apply FUN
> (eql (funcall (on 'equal 'car) > (eql (funcall (on 'equal 'car)
@ -314,7 +329,7 @@
(make-sequence 'vector (- length2 length1) :initial-element fill-value) (make-sequence 'vector (- length2 length1) :initial-element fill-value)
#())) #()))
(defun-ct zipping (result-type &key (fill-value nil fill-value-p)) (defun zipping (result-type &key (fill-value nil fill-value-p))
(lambda (seq1 seq2) (lambda (seq1 seq2)
(let ((length1 (when fill-value-p (length seq1))) (let ((length1 (when fill-value-p (length seq1)))
(length2 (when fill-value-p (length seq2)))) (length2 (when fill-value-p (length seq2))))
@ -331,7 +346,7 @@
(map result-type #'list (map result-type #'list
seq1 seq2))))) seq1 seq2)))))
(defun-ct maximizing (relation measure) (defun maximizing (relation measure)
(lambda (it) (lambda (it)
(let ((it-length (length it))) (let ((it-length (length it)))
(when (> it-length 0) (when (> it-length 0)
@ -346,7 +361,7 @@
it it
(alexandria:iota it-length)))))))) (alexandria:iota it-length))))))))
(defun-ct group-by (fn &key (test 'equal)) (defun group-by (fn &key (test 'equal))
(lambda (seq) (lambda (seq)
(let ((groups (make-hash-table :test test))) (let ((groups (make-hash-table :test test)))
(map nil (map nil
@ -376,3 +391,5 @@
`(alexandria:compose ,@funs)) `(alexandria:compose ,@funs))
(defmacro (&rest funs) (defmacro (&rest funs)
`(alexandria:compose ,@funs)) `(alexandria:compose ,@funs))
(defmacro (&rest funs)
`(alexandria:compose ,@funs))

View File

@ -16,11 +16,11 @@
#:defun-ct #:key #:extract-key #:element #:let-fn #:juxt #:defun-ct #:key #:extract-key #:element #:let-fn #:juxt
#:transform-tail #:slice #:compress-runs #:transform-tail #:slice #:compress-runs
#:combine-matching-lists #:sorted #:applicable-when #:combine-matching-lists #:sorted #:applicable-when
#:of-length #:of-min-length #:of-max-length #:of-length #:of-min-length #:of-max-length #:transform-head
#:transform-head #:maximizing #:zipping #:applying #:maximizing #:zipping #:applying #:splice-elt
#:splice-elt #:transform-elt #:denest #:op #:defalias #:<> #:transform-elt #:denest #:op #:defalias #:<> #:<>1 #:== #:
#:<>1 #:== #: #:suffixp #:functionalize #:inc #:group-by #: #:suffixp #:functionalize #:inc #:group-by #:keys
#:keys #:conj #:disj #:delay)) #:conj #:disj #:delay #:calling))
(defpackage :data-lens.transducers.internals (defpackage :data-lens.transducers.internals
(:use :cl) (:use :cl)

View File

@ -225,6 +225,16 @@
(prog1 (list it count) (prog1 (list it count)
(incf count)))) (incf count))))
'(:p :l :i :s :t))))) '(:p :l :i :s :t)))))
(let ((l '((1 . 2)
(2 . 3)
(3 . 4))))
(5am:is (equal l
(sort (alexandria:hash-table-alist
(data-lens.transducers:into (make-hash-table)
(data-lens.transducers:mapping 'identity)
(alexandria:alist-hash-table l)))
'<
:key 'car))))
(loop for type in '(vector list) (loop for type in '(vector list)
do (5am:is (equalp #(1 2 3 4 5 6) do (5am:is (equalp #(1 2 3 4 5 6)