optparse: Process docstring and declarations correctly in defopthandler.
[lisp] / collect.lisp
CommitLineData
861345b4 1;;; -*-lisp-*-
2;;;
3;;; $Id$
4;;;
5;;; Collecting things into lists
6;;;
7;;; (c) 2005 Straylight/Edgeware
8;;;
9
10;;;----- Licensing notice ---------------------------------------------------
11;;;
12;;; This program is free software; you can redistribute it and/or modify
13;;; it under the terms of the GNU General Public License as published by
14;;; the Free Software Foundation; either version 2 of the License, or
15;;; (at your option) any later version.
16;;;
17;;; This program is distributed in the hope that it will be useful,
18;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;;; GNU General Public License for more details.
21;;;
22;;; You should have received a copy of the GNU General Public License
23;;; along with this program; if not, write to the Free Software Foundation,
24;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
bf0a8c39 26(defpackage #:collect
861345b4 27 (:use #:common-lisp #:mdw.base)
512c44e0 28 (:export #:collecting #:with-collection #:collect #:collect-tail))
bf0a8c39 29(in-package collect)
861345b4 30
31(eval-when (:compile-toplevel :load-toplevel)
32 (defvar *collecting-anon-list-name* (gensym)
33 "The default name for anonymous `collecting' lists.")
34 (defun make-collector ()
a721f2f2
MW
35 (let ((head (cons nil nil)))
36 (setf (car head) head))))
288343df 37
861345b4 38(defmacro collecting (vars &body body)
39 "Collect items into lists. The VARS are a list of collection variables --
0ff9df03
MW
40 their values are unspecified, except that they may be passed to `collect'
41 and `collect-tail' If VARS is empty then *collecting-anon-list-name* is
42 used. VARS may be an atom instead of a singleton list. The form produces
43 multiple values, one for each list constructed."
861345b4 44 (cond ((null vars) (setf vars (list *collecting-anon-list-name*)))
45 ((atom vars) (setf vars (list vars))))
46 `(let ,(mapcar (lambda (v) `(,v (make-collector))) vars)
47 ,@body
447aca39 48 (values ,@(mapcar (lambda (v) `(the list (cdr ,v))) vars))))
288343df 49
861345b4 50(defmacro with-collection (vars collection &body body)
51 "Collect items into lists VARS according to the form COLLECTION; then
0ff9df03 52 evaluate BODY with VARS bound to those lists."
861345b4 53 `(multiple-value-bind
0ff9df03 54 ,(listify vars)
861345b4 55 (collecting ,vars ,collection)
56 ,@body))
288343df 57
861345b4 58(defmacro collect (x &optional (name *collecting-anon-list-name*))
59 "Add item X to the `collecting' list NAME (or *collecting-anon-list-name*
0ff9df03 60 by default)."
a721f2f2
MW
61 (with-gensyms new
62 `(let ((,new (cons ,x nil)))
63 (setf (cdar ,name) ,new)
64 (setf (car ,name) ,new))))
288343df 65
861345b4 66(defmacro collect-tail (x &optional (name *collecting-anon-list-name*))
67 "Make item X be the tail of `collecting' list NAME (or
0ff9df03
MW
68 *collecting-anon-list-name* by default). It is an error to continue
69 trying to add stuff to the list."
861345b4 70 `(progn
a721f2f2
MW
71 (setf (cdar ,name) ,x)
72 (setf (car ,name) nil)))
861345b4 73
74;;;----- That's all, folks --------------------------------------------------