aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README.md45
-rw-r--r--examples.lisp28
-rw-r--r--gtwiwtg.lisp145
3 files changed, 3 insertions, 215 deletions
diff --git a/README.md b/README.md
index c5616b1..fb04b16 100644
--- a/README.md
+++ b/README.md
@@ -87,34 +87,6 @@ example apears at the end of the document, following the tutorial.
```
-### A Silly Scrambler
-
-``` lisp
-
-;; see examples.lisp for defuns of PAD and CHUNK
-
-> (defun scramble (n str)
- (assert (< n (length str)))
- (let ((str (pad str (* n (ceiling (/ (length str) n))))))
- (apply #'concatenate 'string
- (mapcar #'collect (disperse! n (seq str))))))
-
-> (defun descramble (n str)
- (concatenate 'string
- (collect
- (apply #'intersperse!
- (mapcar #'seq (chunk n str))))))
-
-
-> (scramble 3 "this will be scrambled, ya dig?")
-
-"tsi rbdyd?h lbsal,ai iwlecme g "
-
-> (descramble 3 *)
-"this will be scrambled, ya dig? "
-
-```
-
## Tutorial
GTWIWTG is a tiny library for creating and using generators.
@@ -289,23 +261,6 @@ Here are some simple examples of their use:
intermingles the values of its argument generators, in the order
they appear in the argument list.
-And some experimental tools:
-
-- `(nfurcate! n gen)` returns a list of `n` new generators, each
- producing the same elements as of `gen`.
-- `(partition! pred gen)` returns a list of two new generators, the
- first generating the memebers of `gen` that pass the predicate
- `pred`, and the second generating those that don't.
-- `(disperse! n gen)` is sort of the opposite of
- `intersperse!`. Returns a list of `n` generators, the first produces
- every nth value from `gen`, the second produces every nth+1 values
- from `gen`, and so on.
-
-The above are marked as EXPERIMENTAL because they may not be
-in line with the the spirit of this library. I wanted the library to
-produce constant-memory operations. However, when you consume the
-generators that the above forms produce, then new memory will be
-consed during consumption. See the docstrings for both forms for more details.
### A Word Of Warning!
diff --git a/examples.lisp b/examples.lisp
index 0a40a0c..8760b8a 100644
--- a/examples.lisp
+++ b/examples.lisp
@@ -119,31 +119,3 @@ vector VEC, one at a time."
-;;; Silly Scrambler ;;;
-
-
-(defun pad (str len &optional (pad-char #\Space))
- (let ((i 0))
- (with-output-to-string (out)
- (loop :for c :across str :do (incf i) (princ c out))
- (loop :while (< i len) :do (incf i) (princ pad-char out)))))
-
-(defun scramble (n str)
- (assert (< n (length str)))
- (let ((str (pad str (* n (ceiling (/ (length str) n))))))
- (apply #'concatenate 'string
- (mapcar #'collect (disperse! n (seq str))))))
-
-
-(defun chunk (n str)
- (assert (zerop (mod (length str) n)))
- (let ((size (/ (length str) n)))
- (loop
- :for i :below (length str) :by size
- :collect (subseq str i (+ i size)) )))
-
-(defun descramble (n str)
- (concatenate 'string
- (collect
- (apply #'intersperse!
- (mapcar #'seq (chunk n str))))))
diff --git a/gtwiwtg.lisp b/gtwiwtg.lisp
index f1a5038..cb299bd 100644
--- a/gtwiwtg.lisp
+++ b/gtwiwtg.lisp
@@ -474,12 +474,12 @@ Error Conditions:
- If any of the generators compare EQL, an error will be signalled.
- If any of the generators has been used elsewhere, an error will be sigalled.
"
- (sully-when-clean (list* gen gens))
- (inflate! #'identity (seq (list* gen gens))
+ (sully-when-clean (cons gen gens))
+ (inflate! #'identity (seq (cons gen gens))
;; in the case that not all arguments are consumed,
;; explicitly stop each one at clean-up time.
:extra-cleanup (lambda ()
- (dolist (g (list* gen gens)) (stop g)))))
+ (dolist (g (cons gen gens)) (stop g)))))
(defun zip! (gen &rest gens)
"Is a shortcut for (MAP! #'LIST GEN1 GEN2 ...)"
@@ -536,126 +536,6 @@ Error Conditions:
(dolist (g all-gens) (stop g))))))
-(defun skip! (n gen)
- "EXPERIMENTAL. Might be removed.
-
-Returns the generator GEN but without the first N elements.
-
-Caveats:
-
- - It is possible that SKIP! will skip the whole source generator,
- returning an empty gernator.
-"
- (sully-when-clean (list gen))
- (dotimes (x n) (when (has-next-p gen) (next gen)))
- (setf (dirty-p gen ) nil)
- gen)
-
-(defun skip-while! (pred gen)
- "EXPERIMENTAL. Might be removed.
-
-Returns the generator GEN but without the first N elements for
-which PRED is non-nil.
-
-Caveat:
- - It is possible that, for finite generators, skip-while! will skip
- the whole generated sequence.
- - If the generator is infinite, then skip-while! MIGHT never return.
-"
- (sully-when-clean (list gen))
- (let ((cached (list nil)))
- (loop
- :while (has-next-p gen)
- :for val = (next gen)
- :unless (funcall pred val)
- :do
- (setf (car cached) val)
- (return))
- (setf (dirty-p gen) nil)
- (concat! (seq cached) gen)))
-
-
-(defun nfurcate! (count source-generator)
- "EXERIMENTAL. MAY BE REMOVED
-
-Return a list of COUNT copies of GEN.
-
-Caveat:
-
- - The generators produced by NFURCATE! allocate new memory as they
- are consumed. This allocation can be O(COUNT * SIZE) in space
- complexity, where SIZE is the size of GEN. Hence, use with caution
- on infinite generators.
-
- - The SOURCE-GENERATOR will be cleaned up only after all of the
- returned generators have been consumed. That is if you make some
- generators using NFURCATE! but do use them, then the
- SOURCE-GENERATOR may never be cleaned up. I.e. if it is backed by a
- stream, that stream will not be closed.
-
-"
- (sully-when-clean (list source-generator))
- (let ((qs (loop :for _ :below count :collect (make-queue)))
- (stop-cells (loop :for _ :below count :collect (list nil))))
- (loop
- :for build-q :in qs
- :for stop-cell :in stop-cells
- :collect
- (let ((local-q build-q)
- (local-stop stop-cell))
-
- (from-thunk-until
- (lambda ()
- (cond ((not (queue-empty-p local-q))
- (dequeue local-q))
-
- ((has-next-p source-generator)
- (let ((next-v (next source-generator)))
- (loop :for q :in qs :do (enqueue next-v q))
- (dequeue local-q)))
-
- (t (error "Attempted to get next from a spent generator."))))
-
- :until
- (lambda ()
- (and (not (has-next-p source-generator))
- (queue-empty-p local-q)))
-
- :clean-up
- (lambda ()
- (setf (car local-stop) t)
- (when (every #'car stop-cells)
- (stop source-generator))))))))
-
-(defun partition! (pred gen)
- "EXPERIMENTAL. MAY BE REMOVED.
-
-Return a list of two generators that looks like (PASSING FAILING)
-
-PASSING is a generator that produces the values of GEN that pass the
-predicate PRED
-
-FAILING is a generator that produces the values of GEN that do not
-pass the predicate PRED
-
-Caveat:
-
- - The generators produced by PARTITION! allocate new memory as you
- consume them. This allocation may be O(2 * SIZE) in space
- complexity, where SIZE is the size of GEN. Hence, use with caution
- on infinite generators.
-
-- The generator GEN will be cleaned up only after both returned
- generators have been. Hence, you must consume both or you risk
- leaving some clean up undone. E.g. If GEN is a stream backed
- generator, the stream will not be closed until both PASSING and
- FAILING have been consumed.
-
-"
- (destructuring-bind (gen1 gen2) (nfurcate! 2 gen)
- (list (filter! pred gen1)
- (filter! (complement pred) gen2))))
-
(defun intersperse! (gen1 gen2 &rest gens)
"Produces a generator that intersperses one value from each of its
argument generators, one after the other, until any of those
@@ -725,25 +605,6 @@ Example:
"
(map! (lambda (x) (funcall fn x) x) gen))
-(defun disperse! (n gen)
- "EXPERIMENTAL. MAY BE REMOVED.
-
-Produces a list of N gnerators, G1,...,GN.
-
-G1 produces every Nth value of GEN, including first value.
-G2 produces every Nth+1 value of GEN, including the second value.
-...
-GN produces every Nth + (N-1) value of GEN, including the (N-1)th value.
-
-This is sort of the opposite of INTERSPERSE!."
- (loop
- :for i :below n
- :for cloned :in (nfurcate! n gen)
- :collect
- (let ((j i))
- (map! #'second
- (filter! (lambda (pair) (= j (mod (first pair) n)))
- (indexed! cloned))))))
;;; CONSUMERS