From: Len Charest
Subject: (setf (values ...
Date: 
Message-ID: <1991Jun13.204847.5625@jpl-devvax.jpl.nasa.gov>
Anyone out there have CL code for a setf method for values as mentioned on page 129 of CLtL2? The code should handle the case wherein any of the sub-forms of values can themselves have setf methods. Thanks in advance.
-- 
*
Len Charest, Jr.                                       ·······@ai-cyclops.jpl.nasa.gov
JPL Artificial Intelligence Group
*

From: Tim Moore
Subject: Re: (setf (values ...
Date: 
Message-ID: <1991Jun13.170657.23523@hellgate.utah.edu>
In article <·····················@jpl-devvax.jpl.nasa.gov> ·······@AI-Cyclops.JPL.NASA.GOV writes:
>Anyone out there have CL code for a setf method for values as mentioned on page 129 of CLtL2? The code should handle the case wherein any of the sub-forms of values can themselves have setf methods. Thanks in advance.

Assuming setf does the right thing with multiple store values, this
should work:

(define-setf-method values (&rest args &environment env)
  (let ((vars nil)
	(vals nil)
	(store-vars nil)
	(store-forms nil)
	(access-forms nil)
	(nil-store-vars nil))
    (dolist (arg args)
      (multiple-value-bind (these-vars these-vals these-store-vars
			    store-form access-form)
	  (get-setf-method-multiple-value arg env)
	(setq vars (nconc vars these-vars))
	(setq vals (nconc vals these-vals))
	(push (car these-store-vars) store-vars)
	(setq nil-store-vars (nconc nil-store-vars (cdr these-store-vars)))
	(push store-form store-forms)
	(push access-form access-forms)))
    (values (nconc vars nil-store-vars)
	    (nconc vals (make-list (length nil-store-vars)))
	    (nreverse store-vars)
	    `(values ,.(nreverse store-forms))
	    `(values ,.(nreverse access-forms)))))

-- 
Tim Moore                    ·····@cs.utah.edu {bellcore,hplabs}!utah-cs!moore
"Ah, youth. Ah, statute of limitations."
		-John Waters
From: Frank Yellin
Subject: Re: (setf (values ...
Date: 
Message-ID: <FY.91Jun14100902@hardwick.lucid.com>
Tim Moore gives the following setf method for values:
> (define-setf-method values (&rest args &environment env)
>   (let ((vars nil)
> 	(vals nil)
> 	(store-vars nil)
> 	(store-forms nil)
> 	(access-forms nil)
> 	(nil-store-vars nil))
>     (dolist (arg args)
>       (multiple-value-bind (these-vars these-vals these-store-vars
> 			    store-form access-form)
> 	  (get-setf-method-multiple-value arg env)
> 	(setq vars (nconc vars these-vars))
> 	(setq vals (nconc vals these-vals))
> 	(push (car these-store-vars) store-vars)
> 	(setq nil-store-vars (nconc nil-store-vars (cdr these-store-vars)))
> 	(push store-form store-forms)
> 	(push access-form access-forms)))
>     (values (nconc vars nil-store-vars)
>  	    (nconc vals (make-list (length nil-store-vars)))
> 	    (nreverse store-vars)
> 	    `(values ,.(nreverse store-forms))
>	    `(values ,.(nreverse access-forms)))))

I have three very minor nits.  And they really are minor.  I'd be very hard
pressed to write real code for which the above didn't work.

Nit #1) The above code lets each of the <place>'s in (values <place> .. <place>)
itself have a multiple-value setf-method.  Does this really make sense?
Does (setf (values a b (values c d) e) ...) really mean that I want "d" set
to nil? 

I suppose I'm trying to open up the philosophical question of whether there
are places that I really want get-setf-method instead of 
get-setf-method-multiple-value.  Does (push x (values a b)) make any sense?
What about (rotatef (values (values a b)) (values (values c d)))?


Very minor Nit #2)  Temporarily put aside Nit #1.  Using the above code
  > (get-setf-method-multiple-value '(values a (values b c)))
  (#:G3)
  (NIL)
  (#:G1 #:G2)
  (VALUES (SETQ A #:G1) (VALUES (SETQ B #:G2) (SETQ C #:G3)))
  (VALUES A (VALUES B C))

I don't think that the binding of #:G3 to nil should be done as part of the
dummies to values binding.  The binding of newvals to the new values should
only be done as part of the setter.  I would have been happier with

  > (get-setf-method-multiple-value '(values a (values b c)))
  ()
  ()
  (#:G1 #:G2)
 (VALUES (SETQ A #:G1)
  	  (LET ((#:G3 NIL)) (VALUES (SETQ B #:G2) (SETQ C #:G3))))
  (VALUES A (VALUES B C))


Nit #3) The specifications in CLtL2 allow the "newvar" list to be empty!
Sort of silly, but perfectly legal.  The above code implicitly believes
that each newvars list (what is called these-store-vars in the code)
contains at least var.  Imagine one writing the lisp equivalent of
/dev/null:

     (defun hole () (values))
     (def-setf-method hole () () (values))

I would expect something like

  > (get-setf-method-multiple-value (values (hole) a))
  ()
  ()
  (#:G1 #:G2)
  (LOCALLY (DECLARE (IGNORE #:G1))
      (VALUES (VALUES) (SETQ A #:G2)))
  (VALUES (HOLE) A)
	
Where the #:G1 and the (LOCALLY (DECLARE (IGNORE #:G1)) ... ) are created
by the setf method for values.

-- Frank Yellin
   ··@lucid.com
From: Tim Moore
Subject: Re: (setf (values ...
Date: 
Message-ID: <1991Jun14.133747.17543@hellgate.utah.edu>
In article <················@hardwick.lucid.com> ··@lucid.com (Frank Yellin) writes:
>
>Tim Moore gives the following setf method for values:
...
>
>I have three very minor nits.  And they really are minor.  I'd be very hard
>pressed to write real code for which the above didn't work.
>
>Nit #1) The above code lets each of the <place>'s in (values <place> .. <place>)
>itself have a multiple-value setf-method.  Does this really make sense?
>Does (setf (values a b (values c d) e) ...) really mean that I want "d" set
>to nil? 

Yes, according to X3J13 cleanup issue SETF-OF-VALUES. This was passed
at the March 1991 meeting:

Proposal (SETF-OF-VALUES:ADD):
  
  Define VALUES as a SETF place in the standard.

  For a form such as

  (setf (values <place1> .... <placen>) <value-producing-form>)

  the setf methods for each of the nested <placei> are obtained as if by
  GET-SETF-METHOD-MULTIPLE-VALUE.  The order of evaluation is as follows:

  (1) subforms of the nested <placei> are evaluated in left-to-right order.
  (2) The <value-producing-form> is evaluated, and the first store variable
      from each <placei> bound to the values as by MULTIPLE-VALUE-BIND.
      If the setf method for a nested <placei> involves more than one store
      variable, then the additional store variables are bound to NIL.
  (3) Finally the storing forms for the nested <placei> are evaluated in
      left-to-right order.

  Note that (as required by CLtL), the storing form for SETF of VALUES
  returns the values of the store variables as its values.  (This might
  be more or fewer values than what the <value-producing-form> returns.)
>
>Nit #3) The specifications in CLtL2 allow the "newvar" list to be empty!
>Sort of silly, but perfectly legal.  The above code implicitly believes
>that each newvars list (what is called these-store-vars in the code)
>contains at least var. 

Yup, you're right.

-- 
Tim Moore                    ·····@cs.utah.edu {bellcore,hplabs}!utah-cs!moore
"Ah, youth. Ah, statute of limitations."
		-John Waters
From: Erann Gat
Subject: Re: (setf (values ...
Date: 
Message-ID: <1991Jun13.232739.24568@elroy.jpl.nasa.gov>
In article <·····················@jpl-devvax.jpl.nasa.gov> ·······@AI-Cyclops.JPL.NASA.GOV writes:
>Anyone out there have CL code for a setf method for values as mentioned on page 129 of CLtL2? The code should handle the case wherein any of the sub-forms of values can themselves have setf methods. Thanks in advance.

Well, if you really must do such a hideous thing:

(defmacro setf-values (&rest args)
  (let ( (locations (butlast args))
         (form (car (last args))) )
    (let ( (temps (mapcar #'(lambda (s) (gensym "TEMP")) locations)) )
      `(multiple-value-bind ,temps ,form
         ,@(mapcar #'(lambda (loc new-loc) `(setf ,loc ,new-loc))
                   locations temps)))))

(defsetf values setf-values)

E.
From: Mark Kantrowitz
Subject: Re: (setf (values ...
Date: 
Message-ID: <13457@pt.cs.cmu.edu>
In article <·····················@jpl-devvax.jpl.nasa.gov> ·······@AI-Cyclops.JPL.NASA.GOV writes:
> Anyone out there have CL code for a setf method for values as
> mentioned on page 129 of CLtL2? The code should handle the case
> wherein any of the sub-forms of values can themselves have setf
> methods. Thanks in advance.   

What follows is an excerpt from a mail message I sent to a local
mailing list a while ago on this topic. I've omitted the code, since
the changes are specific to the implementation of setf methods in CMU
Common Lisp, but the change to defsetf should be fairly easy to do in
other lisps. Once the change is in place, writing this kind of
multiple value setf method is about as easy as writing a normal
defsetf method. 

I have not heard whether X3J13 is considering anything along these
lines.  

--mark

Return-Path: <···············@GLINDA.OZ.CS.CMU.EDU>
Received: from glinda.oz.cs.cmu.edu by A.GP.CS.CMU.EDU id aa18637;
          25 Dec 90 0:01:36 EST
Date: Mon, 24 Dec 90 16:50:07 EST
From: ···············@GLINDA.OZ.CS.CMU.EDU
To: ···········@B.GP.CS.CMU.EDU
Subject: setf of multiple values
Cc: ·····@A.GP.CS.CMU.EDU

CLtL2 talks a little about setf of multiple values (e.g., the
discussion of get-setf-method-multiple-value), but does not mention
how the multiple values should be specified or even how to define a
setf method.

Anyway, I needed this, so I played around with an implementation by
hacking the definitions of setf, defsetter and defsetf in CMU-CL. 
Since it was extremely desirable that setf retain the syntax
	setf {place newvalue}*
I made the changes such that newvalue could be a form that returned
multiple values. 

I also modified defsetf, so that instead of restricting you to only
one store variable
	defsetf access-fn lambda-list (store-variable) ...
it would allow any number of store variables. For example, if I have
	(defun foo (x)
	  (values (car x) (cadr x)))
instead of having to do 
	(define-setf-method foo (x)
	  (let ((store-1 (gensym))
		(store-2 (gensym))
		(temp-x (gensym)))
	    (values (list temp-x) ; temp for X
		    (list x)        ; the value of X
		    (list store-1 store-2) ; the store variables
		    `(progn ; storing form
		       (rplaca ,temp-x ,store-1)
		       (rplaca (cdr ,temp-x) ,store-2)
		       (values ,store-1 ,store-2))
		    `(foo ,temp-x))))
to define a multiple value setf method, all I need to do is
	(defsetf foo (x) (v1 v2)
	  `(progn
	     (rplaca ,x ,v1)
	     (rplaca (cdr ,x) ,v2)
	     (values ,v1 ,v2)))
Then we have
	* (setq a '(1 2))
	(1 2)
	* (foo a)
	1
	2
	* (setf (foo a) (values 3 4))
	3
	4
	* a
	(3 4)

With this unification of single and multiple values in defsetf, the
distinction between get-setf-method and get-setf-method-multiple-value
seems to be moot.

;;; *EOF*