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

Issue: SETF-METHOD-FOR-SYMBOLS (version 3)



I tried to tighten the discussion section and respond to Moon's
comments. I rewrote the problem description to remove the claim that it
was impossible given the specified setf method for symbols. I'm happy
with Moon's arguments about the likelihood of user programs "copying"
LDB instead of the symbol method.


!

Issue:         SETF-METHOD-FOR-SYMBOLS

References:    CLtL pp. 105, 99. Issue: PUSH-EVALUATION-ORDER.

Category:      CHANGE

Edit history:  Version 1 Moon 21 Sep 87
               Version 2 Masinter 23-Oct-87
               Version 3 Masinter 11-Nov-87


Problem description:

The description of SETF in CLtL and various SETF methods are
inconsistent. The description on page 99 clearly requires side-effects
to be elaborated in left-to-right order; however, the combination of the
sample setf-method for LDB on p.106 and the sample setf-method for
symbols given on p. 105 results in incorrect order of evaluation. 

Test Case A: Given

(LET* ((R (LIST 'A 1 'B 2 'C 3))
       (S R))
  (SETF (GETF R 'B) (PROGN (SETQ R NIL) 6))
  (VALUES R S))

If side-effects are elaborated in left-to-right order, the setq of R to
NIL should not affect the result, since it occurs after R is read and
before R is written, and therefore the value of both R and S should be
(A 1 B 6 C 3).

A typical result in an implementation that believes CLtL p.105 more than
CLtL p.99 is R = (B 6) and S = (A 1 B 2 C 3).

Test Case B: Given:

(LET((A 0))
   (INCF (LDB (BYTE 2 2) A) (SETQ A 2))
   A)

Does this return 8, 10, or 2? If p. 99's description of order of
evaluation is correct, this should return 8.


Proposal: SETF-METHOD-FOR-SYMBOLS:TEMPORARY-VARIABLE

Change the example of the result of

(GET-SETF-METHOD 'FOO) from
NIL NIL (#:G1174) (SETQ FOO #:G1174) FOO

(as currently described in CLtL) to return, for example,

(#:G1175) (FOO) (#:G1174) (SETQ FOO #:G1174) #:G1175

Rationale:

The general principle mentioned on p.99 should override the specific
example on p.105.  The latter is probably just a mistake.

Current practice:

Symbolics and Lucid return the incorrect result mentioned in the test
case A. (Symbolics plans to fix this in the next release.) Franz and
Xerox returns something else: R = nil and S = (a 1 b 6 c 3); Xerox
returns A=10 in Test Case B.   HP Common Lisp produces the recommended
value. 

Spice Lisp returns the recommended value for the test case A, even
though it uses the suggested value for the setf-method for symbols,
because the get-setf-method for GETF introduces additional temporary
bindings.

Adoption Cost:

SETF is an intricate part of Common Lisp, and the fact that not all
implementations currently return the same thing indicates that some care
might be required in updating implementations.  However, in some
implementations changing what get-setf-method returns when its argument
is a symbol is the only change required.

It's been pointed out that this change might cause less efficient code
to be produced in some cases, since setf methods will involve more
temporary variables, however Moon believes that the optimizations are
not difficult and probably are already done by most implementations.

Cost of non-adoption:

Users will think SETF is complicated and hard to understand, because
implementations won't conform to a simple general principle that
side-effects are elaborated in left-to-right order.

Benefits:

Improved portability of Common Lisp programs.

Conversion Cost:

This change is incompatible because it changes the result of some forms
that are not erroneous.  However, it's unlikely that very many users are
intentionally depending on the current behavior.  In addition, the
current behavior is not consistent across implementations, which makes
changing it less problematic.

Esthetics:

See "cost of non-adoption".

Discussion:

A specification of Common Lisp would do well to included some better
examples of precisely what is meant by the "`obvious' semantics"
mentioned on page 99.

This proposal is consistent with PUSH-EVALUATION-ORDER:ITEM in affirming
the left-right order of evaluation of subforms of generalized variable
access forms. 

It was pointed out that it is possible to get the required result for
the test case by modifying the get-setf-method for GETF (and other
setf-able items) to set up the bindings when the modified form is a
symbol, as is done in Spice Lisp. 

However, we believe that user programs are much more likely to have
copied the setf method for LDB given on p.106 than the setf method for
symbols schematized on p.105, and this is the simplest change to achieve
compatibility and correct behavior.