home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.lisp
- Path: sparky!uunet!stanford.edu!lucid.com!karoshi!fy
- From: fy@lucid.com (Frank Yellin)
- Subject: Re: (SETF VALUES)
- In-Reply-To: philpot@kepler.arc.nasa.gov's message of Wed, 6 Jan 1993 21:31:39 GMT
- Message-ID: <FY.93Jan6155542@hardwick.lucid.com>
- Sender: usenet@lucid.com
- Organization: Lucid, Inc., Menlo Park, CA
- References: <1993Jan6.213139.27999@kronos.arc.nasa.gov>
- Date: 6 Jan 93 15:55:42
- Lines: 49
-
-
- In article <1993Jan6.213139.27999@kronos.arc.nasa.gov>
- philpot@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
- fy@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)))))
-