This has particularly useful when dealing with mapping functions for variously libraries. Not sure whether this falls into the scope of Alexandria or not, but I find myself reaching for it often enough that it would be nice to have.
The other question is whether the plural version is really necessary or whether the singular version could be left out in favour of the plural version. Personally, I've only had use for the singular version.
I've attached a patch that includes docstrings and some tests, but I've placed the implementations inline for easy perusal/discussion.
(defmacro with-collector ((name) &body forms) (with-unique-names (list-head list-tail) `(let* ((,list-head (list nil)) (,list-tail ,list-head)) (flet ((,name (object) (rplacd ,list-tail (setq ,list-tail (list object))) object)) ,@forms (cdr ,list-head)))))
(defmacro with-collectors ((&rest names) &body forms) (let ((name-gensyms (make-gensym-list (length names)))) (labels ((%expand-collectors (names name-gensyms) (if names `(setf ,(car name-gensyms) (with-collector (,(car names)) ,(%expand-collectors (cdr names) (cdr name-gensyms)))) `(progn ,@forms)))) `(let ,name-gensyms ,(%expand-collectors names name-gensyms) (values ,@name-gensyms)))))
Basic usage is simply:
(with-collector (collect) (dotimes (x 4) (collect x)))
=> '(0 1 2 3)
Regards,