Subject: Re: The LOOP macro
From: rpw3@rpw3.org (Rob Warnock)
Date: Thu, 25 Mar 2004 04:21:50 -0600
Newsgroups: comp.lang.lisp
Message-ID: <psKcnVYLR_AjL__d3czS-w@speakeasy.net>
Pascal Costanza  <costanza@web.de> wrote:
+---------------
| a wrote:
| >  ...   I'm thinking of a collect that can
| > operate across function call boundaries, is tagged to allow simultaneous
| > collecting to more than one target, and is nestable. It's not so bad to
| > write but if there's a canonical package out there, I'd use it instead of
| > what I'd write.
| 
| For example, see http://www.tfeb.org/lisp/hax.html#COLLECTING
| 
| I recall seeing similar definitions elsewhere, but I don't know here 
| exactly.
+---------------

Also see the EXTENSIONS:COLLECT macro that comes with CMUCL, which
seems to do much the same thing as COLLECTING. The doc string:

  "Collect ({(Name [Initial-Value] [Function])}*) {Form}*
  Collect some values somehow.  Each of the collections specifies a bunch
  of things which collected during the evaluation of the body of the form.
  The name of the collection is used to define a local macro, a la MACROLET.
  Within the body, this macro will evaluate each of its arguments and collect
  the result, returning the current value after the collection is done.
  The body is evaluated as a PROGN; to get the final values when you are
  done, just call the collection macro with no arguments.

  Initial-Value is the value that the collection starts out with, which
  defaults to NIL.  Function is the function which does the collection.
  It is a function which will accept two arguments: the value to be collected
  and the current collection.  The result of the function is made the new
  value for the collection.  As a totally magical special-case, the Function
  may be Collect, which tells us to build a list in forward order; this
  is the default. If an Initial-Value is supplied for Collect, the stuff
  will be rplacd'd onto the end.  Note that Function may be anything
  that can appear in the functional position, including macros and lambdas."

You can use it like this:

	> (collect ((list) (sum 0 +) (prod 1 *))
	    (list :foo)
	    (sum 4)
	    (list :bar :baz :gorp)
	    (when t
	      (prod 7))
	    (loop for i from 10 to 12
	      do (sum i))
	    (prod 6 2)
	    (list :quux)
	    (values (list) (sum) (prod)))

	(:FOO :BAR :BAZ :GORP :QUUX)
	37
	84
	> 


-Rob

p.s. Note that because the variable LIST was MACROLET-bound within
the COLLECT (probably a violation of the CLHS on my part), you can't
use the system LIST within this call. So change the variable name
to MY-LIST...

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607