LOOP has a COLLECT clause which is nice and handy. As a clause however, (COLLECT x INTO y) doesn't work inside forms or nested loops. Various COLLECTING macros have been proposed for this purpose. They can be considered as simple language extensions.
The following shows a typical situation where one wishes for a collecting macro:
There are two basic forms of collecting:
- collect into a single container (and yield the list), like above. It usually takes a form similar to: (collecting (dolist ... (collect form)) ...)
- collect into multiple containers. Two mechanisms are needed: one for naming the desired container, one for selecting the result.
It also uses tail-consing, which was measured by Sam Steingold to be more performant than the PUSH/NREVERSE idiom on several implementations (TODO Reference, c.l.l April 1999 or elsewhere). OTOH, there's an article by Richard C. Waters from 1993 comparing NREVERSE and RPLACD (aka. SETF CDR) where NREVERSE usually wins, presumably because it is heavily optimized by the implementation.
Do you prefer (collect FORM into var) ...) or (var FORM) inside the loops? And what result should be returned by the macro in the presence of multiple variables, would you introduce a FINALLY clause or use VALUES?
Several people have posted their own versions in the long history of c.l.l. IIRC among others Tim Bradshaw (both cases), Bruno Haible, Sam Steingold, and more recently, a naive implementation by Chris Capel. Helmut Eller points at the COLLECT macro available in CMUCL (extensions.lisp):
One could also use an adjustable array and VECTOR-PUSH-EXTEND instead of lists, but that's another story (See c.l.l around November 2001 about "Loop? ptooey" for Dylan code from Bruce Hoult for a generic collecting macro that works on arrays, lists etc.).
macro example accumulators