Turning variables into function names with setf

Discussion of Common Lisp
Post Reply
sabra.crolleton
Posts: 16
Joined: Sat Sep 13, 2008 6:46 pm

Turning variables into function names with setf

Post by sabra.crolleton » Sun Mar 28, 2010 11:10 pm

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

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Turning variables into function names with setf

Post by ramarren » Mon Mar 29, 2010 12:43 am

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.

sabra.crolleton
Posts: 16
Joined: Sat Sep 13, 2008 6:46 pm

Re: Turning variables into function names with setf

Post by sabra.crolleton » Mon Mar 29, 2010 8:47 pm

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.

Post Reply