Page 1 of 1

Turning variables into function names with setf

Posted: Sun Mar 28, 2010 11:10 pm
by sabra.crolleton
I seem to be having conceptual difficulty turning a variable into a function. A simple example is looping through the accessors in a class-instance.
(defclass tst ()
((id :accessor id :initarg :id :initform 0)
(name :accessor name :initarg :name :initform "test-me")))

Then if I have a list of data, I'd like to be able to just loop through the list of accessors. But if I try something like (assume a function get-data exists:
(defun test-commit (item)
(loop for fn in '(id name)
do (setf (funcall fn item) (get-data fn))))

I get a message that (setf funcall) is an undefined function and reserved by ANSI CL

Suggestions or pointers would be appreciated.

Sabra

Re: Turning variables into function names with setf

Posted: Mon Mar 29, 2010 12:43 am
by ramarren
With class accessors a reader and writer are separate functions. To call the writer you need to use its name. In Common Lisp function names can be either symbols or lists of two symbols, the first of which is SETF.

What you are trying to do in your sample (note: use code tags to maintain formatting) is call a (SETF FUNCALL) function which will not work. What you want to do is call a (SETF ID) and so functions, which you can obtain with FDEFINITION and then call:

Code: Select all

(defun test-commit (item)
  (loop for fn in '(id name)
        do (funcall (fdefinition `(setf ,fn)) 'test-data item)))
Easier way, if you don't need accessor instrumentation: use SLOT-VALUE.

Do note that if you want to treat instance slots this way, then what you actually want might be an array or a hash-table.

Re: Turning variables into function names with setf

Posted: Mon Mar 29, 2010 8:47 pm
by sabra.crolleton
Thank you. For most things I would use an array or hash table, but was exploring using a dao-object in postmodern and was looking for a good way for changing an object instance from a list of new data generated elsewhere in the program.