aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gtwiwtg.lisp45
-rw-r--r--package.lisp2
2 files changed, 47 insertions, 0 deletions
diff --git a/gtwiwtg.lisp b/gtwiwtg.lisp
index 1fbf825..93a7922 100644
--- a/gtwiwtg.lisp
+++ b/gtwiwtg.lisp
@@ -293,6 +293,24 @@ distinction.
;;; Some utilities
+(defun make-queue ()
+ (cons nil nil))
+
+(defun enqueue (x q)
+ (push x (car q)))
+
+(defun dequeue (q)
+ (when (and (car q) (null (cdr q)))
+ (setf (cdr q) (reverse (car q))
+ (car q) nil))
+ (when (cdr q) (pop (cdr q))))
+
+(defun queue-empty-p (q)
+ (and (null (car q))
+ (null (cdr q))))
+
+;;; Some assertion tests
+
(defun all-different (things)
(= (length things) (length (remove-duplicates things))))
@@ -545,6 +563,33 @@ returns NIL."
gen)
+(defun nfurcate! (count gen)
+ (make-dirty gen)
+ (let ((qs (loop :for _ :below count-if :collect (make-queue))))
+ (loop :for build-q :in qs
+ :collect
+ (let ((local-q build-q))
+ (from-thunk-until
+ (lambda ()
+ (cond ((not (queue-empty-p local-q))
+ (dequeue local-q))
+
+ ((has-next-p gen)
+ (let ((next-v (next gen)))
+ (loop :for q :in qs :do (enqueue next-v q))
+ (dequeue local-q)))
+
+ (t (error "Attempted to get next from a spent generator."))))
+
+ (lambda ()
+ (and (not (has-next-p gen))
+ (queue-empty-p local-q))))))))
+
+(defun partition! (pred gen)
+ (destructuring-bind (gen1 gen2) (nfurcate! 2 gen)
+ (list (filter! pred gen1)
+ (filter! (complement pred) gen2))))
+
;;; CONSUMERS
(defmacro for (var-exp gen &body body)
diff --git a/package.lisp b/package.lisp
index f84fad6..2629361 100644
--- a/package.lisp
+++ b/package.lisp
@@ -24,6 +24,8 @@
#:merge!
#:skip!
#:skip-while!
+ #:nfurcate!
+ #:partition!
#:for
#:fold
#:collect