3

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.

3
  • 1
    Well a setf function can be a generic function. Expanders can be used for destructuring (e.g. values), and to avoid computing the same thing twice, e.g. if you incf something in a hashtable, you shouldn’t need to hash/lookup the key twice. Commented Feb 16, 2019 at 13:23
  • 3
    "When developing a package" -> setf forms are unrelated to packages. Commented Feb 16, 2019 at 15:51
  • @RainerJoswig Fair enough. :-) Commented Feb 16, 2019 at 16:39

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly the kind of answer I was looking for! Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.