When developing with Common Lisp, we have three possibilities to define new setf-forms:
We can define a function whose name is a list of two symbols, the first one being
setf, e.g.(defun (setf some-observable) (…)).We can use the short form of
defsetf.We can use the long form of
defsetf.We can use
define-setf-expander.
I am not sure what is the right or intended use-case for each of these possibilities.
A response to this question could hint at the most generic solution and outline contexts where other solutions are superior.
define-setf-expanderis the most general of these. All ofsetf's functionality is encompassed by it.Defining a setf function works fine for most accessors. It is also valid to use a generic function, so polymorphism is insufficient to require using something else. Controlling evaluation either for correctness or performance is the main reason to not use a setf function.
For correctness, many forms of destructuring are not possible to do with a setf function (e.g.
(setf (values ...) ...)). Similarly I've seen an example that makes functional data structures behave locally like a mutable one by changing(setf (dict-get key some-dict) 2)to assign a new dictionary tosome-dict.For performance, consider the silly case of
(incf (nth 10000 list))which if thenthwriter were implemented as a function would require traversing 10k list nodes twice, but in a setf expander can be done with a single traversal.