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

setf order of evaluation

I believe the root of this problem is bad interplay between the
following two design issues:

 * I think it was a big mistake to make (SETF var val) work.
   Anyone who's ever implemented SETF knows there's something
   strange about variables that they have to be handled so
   differently than structure accessors. The sense in which
   SETQ makes a side-effect (to a structure which is effectively
   not user-accessible as a first-class object (in dialects not
   having a LOCF extension)) is different than the sense in
   which RPLACA makes a side-effect.

   The fact that
    (DEFUN F (X Y) (PUSH X Y) Y)
   is so radically different in its I/O behavior than
    (DEFUN F (X Y) (PUSH X (CDR Y)) Y)
   is symptomatic of the problem I'm citing.

 * I think there's something odd about GETF in that it takes
   a place as an argument, but nothing can enforce that. eg,
   (GETF '(A B C D) 'C) works, even though (QUOTE ...) is not
   a place. If you try to SETF it, you see the error of your
   ways. The fact that SETF has to reach through the GETF to
   get its first argument and fool with it is what leads to a
   problem like the one I was mentioning above. 

I don't think there's much we can do about this (short of documenting
clearly how this particular special case (and others like it) should be
dealt with). I think it's doomed to be somewhat of an embarrassment
because we've chosen to create a system of rules which I think
inherently cannot generalize in a completely satisfying way.

I'm not advocating that we change SETF at this late date, but if I were
designing a new language, I'd sure advocate doing things differently.

As food for thought, consider the following examples...

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

 ;; #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))

 ;; #3: This can't work, but think hard about why not.
 ;;     There's a sense in which it feels like it ought to be identical
 ;;     to #1 above.
 (PROGN (SETQ R '(A 1 B 2 C 3))
        (SETQ S R)
        (SETF (GETF (NTHCDR 0 R) 'B) (PROGN (SETQ R NIL) 6))
        (VALUES R S))

 ;; #4: This is not as much like the others, but I found its return
 ;;     value to be instructive anyway.
 (PROGN (SETQ R '(A 1 B 2 C 3))
        (SETQ S R)
        (SETF (CAR R) (PROGN (SETQ R NIL) 6))
        (VALUES R S))