Here's the thing: I don't "get" setf-expanders and would like to learn how they work.
I need to learn how they work because I've got a problem which seems like a typical example for why you should learn setf-expanders, the problem is as follows:
(defparameter some-array (make-array 10))
(defun arr-index (index-string)
(aref some-array (parse-integer index-string))
(setf (arr-index "2") 7) ;; Error: undefined function (setf arr-index)
How do I write a proper setf-expander for ARR-INDEX?
(defun (setf arr-index) (new-value index-string)
(setf (aref some-array (parse-integer index-string))
new-value))
In Common Lisp a function name can not only be a symbol, but also a list of two symbols with SETF
as the first symbol. See above. DEFUN
thus can define SETF
functions. The name of the function is (setf arr-index)
.
A setf function can be used in a place form: CLHS: Other compound forms as places.
The new value is the first argument then.
CL-USER 15 > some-array
#(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
CL-USER 16 > (setf (arr-index "2") 7)
7
CL-USER 17 > some-array
#(NIL NIL 7 NIL NIL NIL NIL NIL NIL NIL)
Rainer's answer is spot on. Before ANSI Common Lisp, it was necessary to use defsetf
to define an expander for simple places that could be set with a simple function call. setf
functions like (setf arr-index)
came into the language with CLOS and simplify a lot of things. In particular, setf
functions can be generic.