Consider this piece of code:
(defvar lst \'(1 1))
(defmacro get-x (x lst)
`(nth ,x ,lst))
(defun get-y (y lst)
(nth y lst))
Now let us as
The error does not happen with the macro version, because, as you assumed, the expression (setf (get-x some-x some-list) some-value)
will be expanded (at compile-time) into something like (setf (nth some-x some-list) some-value)
(not really, but the details of setf-expansion are complex), and the compiler knows, how to deal with that (i.e., there is a suitable setf
expander defined for function nth
).
However, in the case of get-y
, the compiler has no setf
expander, unless you provide one. The easiest way to do so would be
(defun (setf get-y) (new-value x ls) ; Note the function's name: setf get-y
(setf (nth x ls) new-value))
Note, that there are a few conventions regarding setf
-expanders:
setf
functionsetf
functions are supposed to return the new value as their result (as this is, what the entire setf
form is supposed to return) There is, BTW, no such concept as a "reference" in Common Lisp (at least not in the C++ sense), though there once were Lisp dialects which had locatives. Generalized place forms (ie., setf
and its machinery) work very differently from plain C++ style references. See the CLHS, if you are curious about the details.