From 5bca9a117f5fe881b3083056b5106af06e063eff Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 4 Jan 2021 00:48:49 -0800 Subject: [PATCH] chore: reorganize transducer definition --- data-lens.asd | 4 ++- lazy-sequence.lisp | 58 ++++++++++++++++++++++++++++++++++++++++ transducer-protocol.lisp | 22 +++++++++++++++ transducers.lisp | 35 ------------------------ 4 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 lazy-sequence.lisp create mode 100644 transducer-protocol.lisp diff --git a/data-lens.asd b/data-lens.asd index b9a0cad..4adfbd1 100644 --- a/data-lens.asd +++ b/data-lens.asd @@ -23,7 +23,9 @@ :serial t :in-order-to ((test-op (test-op :data-lens/transducer/test))) :components ((:file "package") - (:file "transducers"))) + (:file "transducer-protocol") + (:file "transducers") + (:file "lazy-sequence"))) (asdf:defsystem #:data-lens/transducer/test :description "tests for the transducers" diff --git a/lazy-sequence.lisp b/lazy-sequence.lisp new file mode 100644 index 0000000..bb49cc2 --- /dev/null +++ b/lazy-sequence.lisp @@ -0,0 +1,58 @@ +(in-package :data-lens.transducers) + +(defclass lazy-sequence () + ((%next :initarg :next :reader next))) +(defun lazy-sequence (next) + (make-instance 'lazy-sequence :next next)) + +(defmethod reduce-generic ((seq lazy-sequence) (func function) init) + (let ((next (next seq))) + (loop for next-val = (funcall next) + for acc = init then next-acc + for next-acc = (when next-val (funcall func acc next-val)) + while next-val + finally (return acc)))) + +(defmacro repeating (v) + `(lazy-sequence + (lambda () + ,v))) + +(defun repeating* (v &key count) + (lazy-sequence + (if count + (let ((iterations 0)) + (lambda () + (when (< iterations count) + (prog1 v + (incf iterations))))) + (lambda () + v)))) + +(defun iota (&key (start 0) (step 1) count) + (lazy-sequence + (funcall + (compile nil + `(lambda () + (declare (optimize (speed 3) (debug 1) (safety 1))) + (let ((init ,start) + ,@(serapeum:unsplice (when count + '(iterations 0)))) + (declare (type (integer ,start + ,(if count + (+ start (* count step)) + '*)) + init) + ,@(serapeum:unsplice + (when count + `(type (integer 0 ,count) iterations)))) + (lambda () + (declare (optimize (speed 3))) + (,@(if count + `(when (< iterations ,count)) + '(progn)) + (prog1 init + (incf init ,step) + ,@(serapeum:unsplice + (when count + '(incf iterations)))))))))))) diff --git a/transducer-protocol.lisp b/transducer-protocol.lisp new file mode 100644 index 0000000..20353c6 --- /dev/null +++ b/transducer-protocol.lisp @@ -0,0 +1,22 @@ +(in-package :data-lens.transducers.internals) + +(defgeneric unwrap (it obj) + (:method (it obj) obj)) +(defgeneric init (it)) +(defgeneric stepper (it)) + +(defgeneric reduce-generic (seq func init) + (:method ((seq sequence) (func function) init) + (reduce func seq :initial-value init)) + (:method ((seq sequence) (func symbol) init) + (reduce func seq :initial-value init)) + (:method (seq (func symbol) init) + (reduce-generic seq + (symbol-function func) + init)) + (:method ((seq hash-table) (func function) init) + (let ((acc init)) + (maphash (lambda (k v) + (setf acc (funcall func acc (list k v)))) + seq) + acc))) diff --git a/transducers.lisp b/transducers.lisp index 4d2d9ef..2d9c388 100644 --- a/transducers.lisp +++ b/transducers.lisp @@ -1,26 +1,3 @@ -(in-package :data-lens.transducers.internals) - -(defgeneric unwrap (it obj) - (:method (it obj) obj)) -(defgeneric init (it)) -(defgeneric stepper (it)) - -(defgeneric reduce-generic (seq func init) - (:method ((seq sequence) (func function) init) - (reduce func seq :initial-value init)) - (:method ((seq sequence) (func symbol) init) - (reduce func seq :initial-value init)) - (:method (seq (func symbol) init) - (reduce-generic seq - (symbol-function func) - init)) - (:method ((seq hash-table) (func function) init) - (let ((acc init)) - (maphash (lambda (k v) - (setf acc (funcall func acc (list k v)))) - seq) - acc))) - (in-package :data-lens.transducers) (declaim (inline mapping filtering deduping catting splitting @@ -213,18 +190,6 @@ (defmethod unwrap ((it (eql 'list-builder)) obj) (cdr (elt obj 0))) -(defclass lazy-sequence () - ((%next :initarg :next :reader next))) -(defun lazy-sequence (next) - (make-instance 'lazy-sequence :next next)) -(defmethod reduce-generic ((seq lazy-sequence) (func function) init) - (let ((next (next seq))) - (loop for next-val = (funcall next) - for acc = init then next-acc - for next-acc = (when next-val (funcall func acc next-val)) - while next-val - finally (return acc)))) - (defmacro comment (&body body) (declare (ignore body)) nil)