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

(SETF FOO) in next PCL

The next release of PCL includes a fairly significant change related to
the order of arguments of setf functions.  To most all user programs,
this change should be invisible.  Your program should run just fine in
the new version of PCL.  Once you get it running, you will need to do
some conversion however since DEFMETHOD-SETF is now obsolete and will be
going away soon.

Some programs may take some work to adapt to this change.  This will
particularly be true of programs which manipulated methods for setf
generic-functions using make-instance, add-method and friends.

This message gives a brief overview of the upcoming change to PCL.  This
overview is must reading for anyone programming in PCL.  Many people
will find that this message will be all they need to know about this
change.  A subsequent message will present more details which may be
important to people maintaing programs which do more internal hacking.

The CLOS specification assumes a default behavior for SETF in the
absence of any defsetf or define-modify-macro.  The default behavior is
to expand forms like:

   (SETF (FOO x y) a)


   (FUNCALL #'(SETF FOO) a x y)

The key point is that by default, setf expands into a call to a function
with a well-defined name, and that in that call, the new value argument
comes before all the other arguments.

This requires a change in PCL, because previously, PCL arranged for the
new-value argument to be the last required argument.  This change
affects the way automatically generated writer methods work, and the way
that defmethod with a first argument of the form (SETF <symbol>) works.

An important point is that I cannot implement function names of the form
(SETF <symbol>) portably in PCL.  As a result, in PCL, I am using names
of the form |SETF FOO|.  Note that the symbol |SETF FOO| is interned in
the home package of the symbol FOO.  (See the description of the

CertainlyThe user-visible changes will be:

* All programs will need to be completely recompiled to run in this
  release of PCL.

* DEFMETHOD will accept lists of the form (SETF FOO) as a first
  argument.  This will define methods on the generic function named
  by the symbol |SETF FOO|.  As specified in the spec, these methods
  should expect to receive the new-value as their first argument.
  Calls to defmethod of this form will also arrange for SETF of FOO to
  expand into an appropriate call to |SETF FOO|.

* Automatically generated writer methods will expect to receive the new
  value as their first argument.

* DEFMETHOD-SETF will also place the new-value as the first argument.
  This is for backward compatibility, since defmethod-setf itself will
  be obsolete, and you should convert your code to stop using it.

* GET-SETF-FUNCTION is a function which takes a function name and
  returns the setf function for that function if there is one.  Note
  that it doesn't take an environment argument.  Note that this function
  is not specified in Common Lisp or CLOS.  PCL will continue to support
  it as an extra export indefinetely.

* GET-SETF-FUNCTION-NAME is a function which takes a function name
  and returns the symbol which names the setf function for that
  function.  Note that this function  is not specified in Common Lisp
  or CLOS.  PCL will continue to support it as an extra export

* For convenience, PCL defines a macro called DO-STANDARD-DEFSETF which
  can be used to do the appropriate defsetf.  This may be helpful for
  programs which have calls to setf of a generic-function before any
  of the generic function's method definitions.  A use of this macro
  looks like:

     (do-standard-defsetf position-x)

  Afterwards, a form like (SETF (POSITION-X P) V) will expand into a
  form like (|SETF POSITION-X| V P).

  The reason you may have to use do-standard-defsetf is that I cannot
  portably change every implementations SETF to have the new default
  behavior.  The proper way to use this is to take an early file in
  your system, and put a bunch of calls to do-standard-defsetf in it.
  Note that as soon as PCL sees a defmethod with a name argument of
  the form (SETF FOO), or it sees a :accessor in a defclass, it will
  do an appropriate do-standard-defsetf for you.

In summary, the only things that will need to be changed in most
programs is that uses of defmethod-setf should be converted to
appropriate uses of defmethod.

Here is an example of a typical user program which is affected by this

(defclass position ()
    ((x :initform 0 :accessor pos-x)
     (y :initform 0 :accessor pos-y)))

(defclass monitored-position (position)

(defmethod-setf pos-x :before ((p monitored-position)) (new)
  (format *trace-output* "~&Changing x coord of ~S to ~D." p new))

(defmethod-setf pos-y :before ((p monitored-position)) (new)
  (format *trace-output* "~&Changing y coord of ~S to ~D." p new))

To bring this program up to date, you should convert the two
defmethod-setf forms as follows:

(defmethod (setf pos-x) :before (new (p monitored-position))
  (format *trace-output* "~&Changing x coord of ~S to ~D." p new))

(defmethod (setf pos-y) :before (new (p monitored-position))
  (format *trace-output* "~&Changing y coord of ~S to ~D." p new))