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

Re: setf order of evaluation



	
    Date: Fri, 11 Sep 87 14:44 EDT
    From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
    
	Date: Thu, 10 Sep 87 23:13 EDT
	From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
    
         ... 

	 ;; #2: The case in question (using a non-variable as a place)
	 (PROGN (SETQ R '(A 1 B 2 C 3))
		(SETQ S R)
		(SETF (GETF (NTHCDR 2 R) 'B) (PROGN (SETQ R NIL) 6))
		(VALUES R S))
    
    ...

    ;; #2a: doesn't use GETF at all
    (PROGN (SETQ R '(A 1 B 2 C 3))
	   (SETQ S R)
	   (SETF (NTHCDR 2 R) (PROGN (SETQ R NIL) 6))
	   (VALUES R S))
    which again blows up with CLtL's setf-method for variables, but does
    what one would expect with the one I suggested.  These two examples
    changed my mind; now I think the one I suggested is obviously right,
    and the one in CLtL, evidently used by Symbolics and Lucid (and no
    doubt other implementations) is obviously wrong.
    
Minor point: NTHCDR is not a standard generalized variable in CLtL.
Major point: Does the following example change your mind back?

(PROGN (SETQ R (LIST (LIST A 1 B 2 C 3)))
       (SETQ S (CAR R))
       (SETF (GETF (CAR R) 'B) (PROGN (SETF (CAR R) NIL) 6))
       (VALUES R S))
I'll bet that SCL currently returns
(A 1 B 2 C 3) ; ((B 6))
regardless of variable setf-method used.  But it should return
(A 1 B 6 C 3) ; (NIL)
As JonL (I think) implicitly pointed out, it is the responsibility of GETF to
evaluate the access-form of the sub-setf-method (e.g., (CAR G0001)).
It is NOT the responsibility of the sub-setf-method.  Otherwise the
setf-method for (CAR exp) would have to look like
(G0001 G0002)
(exp (CAR G0001))
(G0003)
(PROGN (RPLACA G0001 G0003) G0003)
G0002

Here's another GETF puzzle (only for implementations that did the
right thing above):

(PROGN (SETF S (LIST (LIST A 1 B 2 C 3)))
       (SETF R (CAR S))
       (SETF (GETF (CAR S) 'D) (PROG1 4 (SETF (CAR S) NIL)))
       (VALUES R S))
could legally return:
#1=(A 1 B 2 C 3) ; (D 4 . #1#) {if new pairs are added to the front}
(A 1 B 2 C 3 D 4) ; NIL {if new pairs are added not at the front, and
   the sub-update-form is not used}
#1=(A 1 B 2 C 3 D 4) ; #1# {if new pairs are added not at the front,
and the sub-update-form is used}

One final SETF puzzle:

(PROGN (SETF S (LIST (LIST 1)))
       (SETF R (CAR S))
       (SETF (CAAR S) (PROG1 2 (SETF (CAR S) (LIST NIL))))
       (VALUES R S))
Is this valid?
(1) ; ((2)) {I think: Yes definitely.}
Is this?
(2) ; ((NIL)) {I think: Probably not.}
Try it in your implementation.
Hint:  The big issue here is when the setf-method gets a handle on
the object whose cell is being stored into.  The definition of DEFSETF
strongly implies that the first choice is the correct one.

-- Nick