From: Kent M Pitman
Subject: Re: changing second return value of (values..) after unwind-protect
Date: 
Message-ID: <sfwlndnda3g.fsf@world.std.com>
ยทยท@mail.pls (Daitaro Hagihara) writes:

> Is there a way to change the second return value of (values..) statement
> wrapped around in unwind-protect?  For exampel, I can do
> 
> (let ((x '(1 2))) (unwind-protect x (setf (car x) 3))) --> '(3 2)
> 
> But the following returns not what I would hopled for:
> 
> (let ((x '(1 2))) (unwind-protect (values-list x) (setf (car x) 3))) --> 1,2
> 
> not 3,2 that I was hoping for.  Likewise similar results for values instead of
> values-list.  I can understand why this is the case.  Just curious to know
> if there is a way around.  TIA

Aside: You should never change the car or cdr of any list created with QUOTE.
   In your example, you want (list 1 2) not '(1 2) unless you want to
   risk strange consequences. For example, such a modification of quoted
   structure might get you an error due to writing a read-only page or
   it might make a side-effect on all constant lists (1 2) in your image
   or other bad things like that.

I suspect based on your query that you are doing something that is
just wrong since there can't be any meaningful reason to
unconditionally change a return value when you don't know that a
return value is happening.  Nevertheless, I'll play along in hopes
this answers your underlying question, which may have gotten lost in
trying to present a simple example to this forum.

First, VALUES-LIST is mis-named.  (If it were named in the style of
CHAR-CODE and CODE-CHAR, VALUES-LIST would be called
LIST-VALUES. Sigh.)  It does not yield a list.  It takes a list and
returns separate values which are the result of picking apart the
list.  There is nothing to RPLACA. This is the entire function of
VALUES in the language, btw; if there were going to be a structure,
we'd not have bothered since existing structures are enough.  VALUES
exist in order to sometimes not have to cons on return values, and
where nothing is consed, there is no structure to change.  You CAN, of
course, do the following but that may not work in a real situation.

 (let ((x (list 1 2)))
   (unwind-protect (progn ... x) ;returns a list, not multiple values
     (setf (car x) 3)) ;modifies the list, whose identity is assumed
   (values-list x)) ;finally turns the list into values

However, in general, the guard clauses in an unwind-protect have no
way to see what value (if any) is being returned.  As I mentioned, it
would be somewhat meaningless if it did have a way, since you wouldn't
know to where the value was being returned.

If, as your need to ask this question implies, you care only about
"normal" return, not "non local transfer of control" (explicit or
implicit calls to THROW, RETURN-FROM, or GO), the situation is much
easier since you don't need UNWIND-PROTECT.  You can just pick up
the return values, change them, and return new return values. For
example:

 (defun foo () (values 1 2 3))

 (let ((x (multiple-value-list (foo))))
   (setf (cadr x) 17) ;assumes you know for sure two values come back
                      ;otherwise, you need error-checking for short lists
   (values-list x))
 => (1 17 3)