From: barmar@think.com (Barry Margolin)
Subject: CLOS With-Accessors
Organization: The Ohio State University Department of Computer and Information Science
Date: Wed, 8 Apr 1992 09:09:00 GMT

    Date: Wed, 8 Apr 1992 11:21 EDT
    From: Guy@AVON.sltd.dialnet.symbolics.com (Guy Footring)

    I have a couple of queries about the use of With-Accessors in CLOS
    that I would appreciate some help with.

Since CLOS is not specific to Symbolics machines, it would probably be
better if you posted to a CLOS-specific mailing list
comp.lang.lisp@cis.ohio-state.edu (and if you have Usenet access, this
is equivalent to the comp.lang.lisp newsgroup).  I've cc'ed this reply
to that list (and if you reply via the newsgroup, please also send a
copy to Guy since he probably doesn't read it).

    Perhaps the easiest way of explaining my queries is with some example code
    and asking if the code is legal, and if not why not.

    Example 1:

    (defclass A ()
	((a-slot :initform 0)
	 (a-slot2 :initform 0 :reader a-slot2 )))

    ;;; Always lie about what's in a-slot
    (defmethod a-slot ((A A))
      (* (slot-value A 'a-slot) 0.9))

    ;;; Better stay consistent
    (defmethod (setf a-slot) (value (A A))
      (setf (slot-value A 'a-slot) (* value (/ .9)))
      value)

    ;;; Now use WITH-ACCESSORS with a home-brew accessor 
    (defmethod foo ((A A))
      (with-accessors ((a-slot a-slot)) A
	(incf a-slot 5)))

    (defmethod foo2 ((A A))
      (with-accessors ((a-slot2 a-slot2)) A
	a-slot2))

    Is the method FOO valid since it isn't using system defined accessors?
    Is the method FOO2 valid, since A-SLOT2 is only a reader method, but I'm only using
    the 'accessor' in reader mode?

    Example 2:

    (defclass B ()
	((b-slot :initform 1 :accessor b-slot)))


    ;;; Class C REQUIRES that Class B will be mixed in when any C's are instantiated
    (defclass C ()
	((c-slot :initform 2 :accessor c-slot )))


    (defmethod bar ((C C))
      (with-accessors ((b-slot b-slot)) C
	(incf b-slot)))

    (defmethod baz ((C C))
      (with-slots (b-slot) C
	(incf b-slot)))

    (defclass D (B C)
	())


    Are the methods BAR and BAZ legal, i.e. can With-Accessors and With-Slots be used 
    with accessors/slots that won't be available until run-time?

    All the above compiles and runs as I would hope on a Symbolics, but is this portable?
    Is any of this implementation dependent?

    Thanks in advance for any help that may be forthcoming,
    Guy Footring.

I was going to answer that all of these were OK, but I did some checking
in CLtL2, the original CLOS spec approved by X3J13, and the draft of the
CL standard, and now I'm not so sure.

P.777 of CLtL2 contains the restriction "Any accessors specified by
WITH-ACCESSORS must already have been defined before they are used";
this line comes direct from the CLOS spec.  And the ANSI draft's
description of WITH-ACCESSORS says, "The consequences are undefined if
any accessor-name is not the name of an accessor for the instance."

In the case of the first quote, I'm not sure what it means by "used";
does it mean "called" (i.e. at runtime), or does it mean "seen by the
compiler"?  I'd like to think that the former was intended, but that's
true of *all* functions so I don't think the designers would have made a
special point of it.

The second quote has me even more confused.  It may be intended just to
restate the restriction in the first quote.  This sense of the term
"accessor" is never defined precisely in the standard (there's a
definition of "accessor" that refers to generalized references -- e.g.
CAR is this kind of accessor).  Nowhere is it ever stated that :ACCESSOR
defines this kind of accessor; it is just a shorthand for defining the
appropriate methods yourself (it might also make use of
implementation-specific optimizations, but those should be transparent
unless you're timing or using the metaobject protocol).

Finally, these restrictions appear to contradict other parts of the CLOS
spec, which say that WITH-ACCESSORS is equivalent to a use of
SYMBOL-MACROLET that replaces the "variable" references with calls to
the specified accessor.  Why should this SYMBOL-MACROLET expansion be
dependent on how the accessor is defined?

                                                barmar
Newsgroups: comp.lang.clos