[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Common LISP omissions: Collect, Locatives
We have been using Common LISP and have noticed two
important omissions in the language.
1) Locatives ("LOCF" as found in ZetaLISP).
2) A COLLECT macro.
A primary reason for locatives would be to create your own
"hash-on-eq" functions. Common LISP provides SXHASH which
hashes on equal. A serious problem occurs if the keys are
circular objects.
A collect macro would allow the construction of lists
maintaining the order of creation. Currently, the only way
to produce the same effect, would be to use PUSH and the
NREVERSE. If the programmer intends to use the partially
constructed list, it would need to be REVERSEd each time.
An example of the collection macro could look like:
(DEFMACRO With-Collection (vars &body body)
(LET (collects gensym)
(DOLIST (var vars)
(SETQ gensym (GENSYM var))
(PUSH gensym (GET var :collect))
(PUSH gensym collects))
(PROG1
`(LET (,@vars ,@collects)
,@(Macroexpand-All body))
(DOLIST (var vars) (POP (GET var :collect)))))
)
(DEFMACRO Collect (obj place)
(LET ((endptr (CAR (GET place :collect))))
`(COND
(,place (SETF (CDR ,endptr) (NCONS ,obj))
(SETQ ,endptr (CDR ,endptr)))
(T (SETQ ,place (NCONS ,obj))
(SETQ ,endptr ,place))))
)
(DEFUN Macroexpand-All (form &AUX (mac (MACROEXPAND form)))
(IF (CONSP form)
(CONS (Macroexpand-All (CAR mac)) (Macroexpand-All (CDR mac)))
mac))
It would be easier to implement the collect macro if a
function like LOCF existed. Furthermore, we would not need
to check the partially constructed list each time to
determine whether it was still empty (see the COND in
#'Collect).
ZetaLISP's LOOP macro includes the collect facility, but
collection should be possible outside of a loop (for
example, when searching through a graph).
David Loewenstern
Mark Silbert
Naval Air Development Center, code 7013
Warminster, PA 18974
<dml@nadc.arpa>
<silbert@nadc.arpa>