Search code examples
lispcommon-lispallegro-cl

How can I do setf on a struct's accessors when using intern


I'd like to setf different fields of a struct depending on a certain variable. I decided to use the following approach:

Generate a string with the field's accessor name:

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))

and then use intern with funcall:

(funcall (intern my-string) *estadisticas*)

This call returns the correct value of the struct's field, but if I try setf to modify this value it complains saying:

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound

I can understand why it doesn't work, but I can't find a way to modify the struct's fields. Any idea? Thank you.


Solution

  • You want to call a writer function of the struct via its name, and the name of the writer is the list (setf accessor-name); so

    (funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)
    

    Edit:

    Not seeing the rest of your code, it's hard to fathom what went wrong. On SBCL this works for me:

    (defstruct point x y)
    (let ((point (make-point :x 1 :y 2)))
      (funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
      point)
    

    The above evaluates to

    #S(POINT :X 10 :Y 2),
    

    as expected.