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

[barmar@Think.COM: MULTIPLE-VALUE-SETQ and SYMBOL-MACROLET interaction]



MULTIPLE-VALUE-CALL is the wrong thing to use here, since it forces
the number of values to match the number of variables.  The correct
thing is to use MULTIPLE-VALUE-BIND.  Here is a modified version of
EXPAND-WITH-SLOTS-INTERNAL:

(defun expand-with-slots-internal (specs form context translate-fn &aux entry)
  (cond ((not (eq context :eval)) form)
	((symbolp form)
	 (if (setq entry (assoc form specs))
	     (funcall translate-fn (cadr entry))
	     form))
	((not (listp form)) form)
	((member (car form) '(setq setf))
	 ;; Have to be careful.  We must only convert the form to a SETF
	 ;; form when we convert one of the 'logical' variables to a form
	 ;; Otherwise we will get looping in implementations where setf
	 ;; is a macro which expands into setq.
	 (let ((kind (car form)))
	   (labels ((scan-setf (tail)
		      (if (null tail)
			  nil
			  (walker::relist*
			    tail
			    (if (setq entry (assoc (car tail) specs))
				(progn (setq kind 'setf)
				       (funcall translate-fn (cadr entry)))
				(car tail))
			    (cadr tail)
			    (scan-setf (cddr tail))))))
	     (let (new-tail)
	       (setq new-tail (scan-setf (cdr form)))
	       (walker::recons form kind new-tail)))))
	((eq (car form) 'multiple-value-setq)
	 (let* ((vars (cadr form))
		(gensyms (mapcar #'(lambda (i) (declare (ignore i)) (gensym))
				 vars)))
	   `(multiple-value-bind ,gensyms 
		,(caddr form)
	      .,(mapcar #'(lambda (v g) `(setf ,v ,g))
					       vars
					       gensyms))))
	(t form)))