[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Writing Destructive Functions
- To: jbk@world.std.com (Jeffrey B Kane)
- Subject: Re: Writing Destructive Functions
- From: kab (Kim Barrett)
- Date: Tue, 22 Sep 92 14:23:16 EST
- Cc: info-mcl@cambridge.apple.com, ranson@LANNION.cnet.fr
> The LISP way out seems to be using (multiple-value-bind) but this is a
> very clumsy macro that makes it awkward to change mulitple variables
> within the block, i.e.
>
> (let ((x 0) (y 0))
> ;; do something with x & y
> (multiple-value-bind (m n)
> (truncate 3.4565)
> (setf x m)
> (setf y n))
> ;; do something else with x & y
> )
For this particular case you should use multiple-value-setq. For more general
cases you could use setf of values, except that MCL2.0 doesn't provide it.
It's fairly easy to write, though. In fact, just for fun, here's a possible
definition (called values* here instead of values). I haven't done any serious
testing of it, but its sufficiently trivial that it should work.
(define-setf-method values* (&rest places &environment env)
(let ((all-vars ())
(all-vals ())
(all-stores ())
(setters ())
(getters ()))
(dolist (place places)
(multiple-value-bind (vars vals stores setter getter)
(get-setf-method place env)
(setf all-vars (revappend vars all-vars))
(setf all-vals (revappend vals all-vals))
(push (car stores) all-stores)
(push setter setters)
(push getter getters)))
(values (nreverse all-vars)
(nreverse all-vals)
(setf all-stores (nreverse all-stores))
`(progn ,@(nreverse setters) (values ,@all-stores))
`(values ,@(nreverse getters)))))
> You get the idea. I could use macros but, having been burned many times
> in the past (especially in C) I would much prefer to write real functions.
Writing Common Lisp macros, setf methods, &etc is generally not all that
difficult once you become familiar with the tools and idioms. In particular,
because of things like gensym, trivial syntax, backquote, and similar features,
it is usually easy to write macros that avoid the various "shoot yourself in
the foot" problems encountered with the trivial text substitution style of
macros provided by C and similar languages. For example, using gensym to
establish "hidden" bindings that ensure single evaluation in normal order.
There's also none of this "statement vs expression" dichotomy to make the life
of a would-be macro writer unpleasant. Unfortunately, this seems to be one of
the more poorly taught areas of the language.