Subject: Re: [Info req] Problem using funcall in setf
From: Erik Naggum <erik@naggum.no>
Date: 1999/11/24
Newsgroups: comp.lang.lisp
Message-ID: <3152473610386435@naggum.no>

* Anthony Herana <aherana@farad.ee.calpoly.edu>
| I have this line of code:
| 
|  (setf (funcall part-type user-profile) (list part-instance))
| 
| where part-type contains a symbol that I want to now use as an accessor of
| a pre-defined class, user-profile is the class instance, and part-instance
| is an object I want to put into a list and assign that list to the data
| member in user-profile.

  I'm not sure I follow you.  are you trying to write into different slots
  of the instance of a known class through variable accessors?  may I
  recommend that you use these forms instead:

(slot-value <instance> <slot-name>)
(setf (slot-value <instance> <slot-name>) <new-value>)

  and not go through the accessor?  if you already considered and discarded
  this, I'd like to hear your reason.

| The expression with the funcall works when I run it separately, as does
| the list expression.  It's only when I put them into the setf expression
| that lisp barks at me.  Could someone please enlighten me as to what I am
| doing incorrectly?

  SETF is a macro, so it needs to resolve the argument at compile-time,
  whereas what you observe to work happens solely at run-time.  so to make
  this work, you need to figure out what SETF would have produced in the
  constant case.  assuming you have built the accessor with an :ACCESSOR
  slot option, it is actually a list of the form (SETF x), where x is the
  name of the reader.  (this is called a "function name".)

  that is, if (foo-slot-accessor foo-instance) is the access form, then
  (setf (foo-slot-accessor foo-instance) new-value) will expand into
  (funcall (function (setf foo-slot-accessof)) new-value foo-instance).

  ordinarily, you would have to use (FUNCTION (SETF x)) to get at this
  function, but this is a quoted constant, so you lose with a variable x.
  however, the accessor FDEFINITION will accept a function name constructed
  at run-time.  (fdefinition (list 'setf <getter>)) will return the setter
  function.  so you could write

(funcall (fdefinition (list 'setf part-type)) (list part-instance) user-profile)

  and lose in both categories "elegance" and "performance", because this is
  not only ugly, it's defeating optimization opportunities left and right.
  so you would probably end up using SLOT-VALUE directly to save yourself.

  what's wrong with accessors if this is what you have to do?  nothing, of
  course, but they are intended for human-readable code where the name of
  the accessor is communicating some form of intent.  inside a function
  that just reads and sets slots, such concerns have very limited value
  when they detract from a working solution.

[ I have used (function X) instead of the abbreviated form #'X to avoid any
  possible confusion.  FUNCTION is a quoting form like QUOTE, and as 'x is
  identical to (quote x), #'x is identical to (function x). ]

#:Erik, who enjoyed figuring this one out and hope this helps