I have a list which contains some symbols and values. The goal is to setf the class slot with the accessor, whose symbol is provided by the list :
(defclass my-class ()
((attr :accessor attr)))
(let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(setf `(,(car to-call) obj) (cadr to-call)))
I have tried via a macro :
(defmacro call-accessor (to-call)
`(setf (,(car to-call) obj) "some-value"))
(let ((to-call '(attr "some-value"))
(obj (make-instance 'my-class)))
(call-accessor to-call))
Which fails too, since to-call
is a symbol and not a list.
eval
does not work sinceto-call
is a lexical variable;- It is not possible to do a
let
over the macro to give it the list; - I have tried with
with-slots
andwith-accessors
but the problem remains the same, because they are macros too. - I have considered macros which declares other macro, and symbol-macrolet too.
How can I setf a slot via an accessor corresponding to a symbol in my list ?
Thank you.
Calling the accessor function
An accessor is a pair of functions. You can get the part which sets the value via
FDEFINITION
. The name of the function is a list(SETF accessor-name )
. This is unusual: Common Lisp has in this case function names which are not symbols, but lists.Using a function
call-accessor
:using SETF with APPLY to hide the FDEFINITION call
To use
setf
with a computed accessor, one might need to use anapply
form and a custom function.Something like
call-accessor
would naturally be a function, because it does runtime lookup and takes values. Trying to use a macro would be more useful if the accessor would be known at compile time.Choice of data structure
I think it's okay to compute accessor functions and similar. There may be use cases for that. CLOS was designed to be dynamic and reflective to allow these things.