What are the typical use-cases of (defun (setf …)) defsetf and define-setf-expander

565 Views Asked by At

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.

1

There are 1 best solutions below

1
Jason On BEST ANSWER

define-setf-expander is the most general of these. All of setf'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 to some-dict.

For performance, consider the silly case of (incf (nth 10000 list)) which if the nth writer were implemented as a function would require traversing 10k list nodes twice, but in a setf expander can be done with a single traversal.