Is it possible to implement (SETF VALUES) in a Lisp which doesn't
already do this?
This is (will be) part of lisp, e.g., as per section 5.1.2.3 of the
dpans, but my vendor hasn't implemented it yet.
I thought it should be possible, and worked on this awhile, but
couldn't seem to get it to work. VALUES is "just" a function, after
all, not a special form/special operator. I don't have a lot of
experience with DEFINE-SETF-METHOD (now DEFINE-SETF-EXPANDER); I don't
think the simpler routes will work (will they?). I imagine that a
home-brewed version would be less efficient than a built-in one, but
perhaps compile-time transformations could result in pretty good code.
If anyone has done this in a (stock hardware) Lisp, or knows good
reasons why it can or cannot be done, please let me know or post.
Andrew Philpot - "not a rocket scientist"
·······@ptolemy.arc.nasa.gov
In article <·····················@kronos.arc.nasa.gov>
·······@kepler.arc.nasa.gov (Andrew Philpot) writes:
> Is it possible to implement (SETF VALUES) in a Lisp which doesn't
> already do this?
Always happy to help.
-- Frank Yellin
··@lucid.com
(define-setf-method values (&rest arguments &environment environment)
(let (all-dummies all-values all-newvals all-setters all-getters)
(dolist (place arguments)
;; look at each of the place arguments
(multiple-value-bind (dummies values newvals setter getter)
;; get the setf method for each place argument
(get-setf-method-multiple-value place environment)
;; collect all the dummies, and the values to bind them to
(push dummies all-dummies) ; list of dummies for each place
(push values all-values) ; list of values for each place
(push getter all-getters) ; list of getters for each place
;; Collect the setters and the newvals variables. This is
;; slightly complicated if (length newvals) isn't 1. For example,
;; (setf (values a (values b c) d) ...) should always set c to
;; 'nil, and (setf (values (values) b) ...) should just ignore the
;; first value passed.
(cond ((null newvals)
;; Will this ever happen? A setf method expecting no newvals?
;; Create a gensym to gets its value, and ignore it
(let ((temp (gensym)))
(push temp all-newvals)
(push `(locally (declare (ignore ,temp)) ,setter) all-setters)))
((null (cdr newvals)) ; The most common case.
;; Just collect the setter and the single newval slot
(push (car newvals) all-newvals)
(push setter all-setters))
(t
;; The place argument expects multiple values. Bind all but
;; the first one to nil in the setter.
(push (car newvals) all-newvals)
(push `(let ,(cdr newvals) ,setter) all-setters)))))
;; Return the five values
(values (apply 'nconc (nreverse all-dummies))
(apply 'append (nreverse all-values))
(nreverse all-newvals)
`(values ,@(nreverse all-setters))
`(values ,@(nreverse all-getters)))))
In article <···············@hardwick.lucid.com> ··@lucid.com (Frank Yellin) writes:
>
> > Is it possible to implement (SETF VALUES) in a Lisp which doesn't
> > already do this?
>
Pardon my ignorance here, but could you explain in what situations one would
wish to do this?
--
Steve Jameson General Electric Aerospace / Martin Marietta
········@atl.ge.com Advanced Technology Laboratories
Moorestown, New Jersey
****************************************************************************
** . . . but I do not love the sword for its sharpness, nor the arrow **
** for its swiftness, nor the warrior for his glory. I love only that **
** which they defend . . . **
** -- Faramir, "The Two Towers" **
****************************************************************************
In article <·····················@fergie.atl.ge.com> ········@atl.ge.com writes:
>In article <···············@hardwick.lucid.com> ··@lucid.com (Frank Yellin) writes:
>> > Is it possible to implement (SETF VALUES) in a Lisp which doesn't
>> > already do this?
>Pardon my ignorance here, but could you explain in what situations one would
>wish to do this?
The normal multiple-value assignment operators only allow you to assign to
variables, but you might want to assign to a set of generalized references.
Here's a simple, contrived example:
(defstruct (q-and-r (:conc-name qr-))
quotient
remainder)
(defvar *qr* (make-q-and-r))
...
(setf (values (qr-quotient *qr*) (qr-remainder *qr*))
(floor numerator denominator))
--
Barry Margolin
System Manager, Thinking Machines Corp.
······@think.com {uunet,harvard}!think!barmar
In article <···········@early-bird.think.com> ······@think.com (Barry Margolin) writes:
> In article <·····················@fergie.atl.ge.com> ········@atl.ge.com writes:
> >In article <···············@hardwick.lucid.com> ··@lucid.com (Frank Yellin) writes:
> >> > Is it possible to implement (SETF VALUES) in a Lisp which doesn't
> >> > already do this?
> >Pardon my ignorance here, but could you explain in what situations one would
> >wish to do this?
>
> The normal multiple-value assignment operators only allow you to assign to
> variables, but you might want to assign to a set of generalized references.
> Here's a simple, contrived example:
>
> (defstruct (q-and-r (:conc-name qr-))
> quotient
> remainder)
>
> (defvar *qr* (make-q-and-r))
> ...
> (setf (values (qr-quotient *qr*) (qr-remainder *qr*))
> (floor numerator denominator))
Thank you, I understand now. I don't have a Cltl2 or draft standard handy, but
isn't there such a thing as multiple-value-setf which would serve exactly this
purpose?
> --
> Barry Margolin
> System Manager, Thinking Machines Corp.
>
> ······@think.com {uunet,harvard}!think!barmar
--
Steve Jameson General Electric Aerospace / Martin Marietta
········@atl.ge.com Advanced Technology Laboratories
Moorestown, New Jersey
****************************************************************************
** . . . but I do not love the sword for its sharpness, nor the arrow **
** for its swiftness, nor the warrior for his glory. I love only that **
** which they defend . . . **
** -- Faramir, "The Two Towers" **
****************************************************************************
········@atl.ge.com writes:
> Thank you, I understand now. I don't have a Cltl2 or draft standard handy, but
> isn't there such a thing as multiple-value-setf which would serve exactly this
> purpose?
There is MULTIPLE-VALUE-SETQ, but this one only handles symbols as places.
The good thing about the (VALUES ...) place is that it makes
MULTIPLE-VALUE-SETQ obsolete. You can also write macros LETF and LETF* that
make MULTIPLE-VALUE-BIND obsolete. You can then write
(letf* (((values x y) (values (car l) (cdr l)))
((values q r) (floor x y)))
(foo q r)
)
which expands into
(let ((x (car l)) (y (cdr l)))
(multiple-value-bind (q r) (floor x y)
(foo q r)
) )
Bruno Haible
······@ma2s2.mathematik.uni-karlsruhe.de
In article <······················@fergie.atl.ge.com> ········@atl.ge.com writes:
>Thank you, I understand now. I don't have a Cltl2 or draft standard handy, but
>isn't there such a thing as multiple-value-setf which would serve exactly this
>purpose?
No, there's only a MULTIPLE-VALUE-SETQ.
In hindsight, having separate SETQ and SETF was a bad design, IMHO.
--
Barry Margolin
System Manager, Thinking Machines Corp.
······@think.com {uunet,harvard}!think!barmar