[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Writing Destructive Functions



> 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.