(defun (setf …))、defsetf和define-setf-expander的典型用例是什么?

3
当使用Common Lisp进行开发时,我们有三种可能性来定义新的setf-forms:
  • 我们可以定义一个函数,其名称是两个符号的列表,第一个符号为setf,例如defun (setf some-observable) (…)。
  • 我们可以使用defsetf的简短形式。
  • 我们可以使用defsetf的长形式。
  • 我们可以使用define-setf-expander。
我不确定每种可能性的正确或预期用例。
对此问题的回复可能会提及最通用的解决方案,并概述其他解决方案优越的情况。

1
setf函数可以是一个通用函数。扩展器可用于解构(例如values),并避免重复计算相同的内容,例如如果您在哈希表中使用incf对某些内容进行增量操作,则不需要两次哈希/查找键。 - Dan Robertson
3
当开发一个包时,setf表达式与包无关。 - Rainer Joswig
@RainerJoswig 好的,没问题。 :-) - Michaël Le Barbier
1个回答

5

define-setf-expander是这些函数中最通用的。它包含了所有setf的功能。

对于大多数访问器,定义一个setf函数就可以了。使用通用函数也是有效的,因此多态性不足以要求使用其他东西。控制评估以确保正确性或性能是不使用setf函数的主要原因。

对于正确性来说,很多形式的解构都无法使用setf函数(例如(setf (values ...) ...))。同样,我曾经看到过一个例子,通过将(setf (dict-get key some-dict) 2)更改为将新字典分配给some-dict,使函数数据结构在本地像可变数据结构一样运行。

对于性能来说,考虑一个愚蠢的情况:(incf (nth 10000 list)),如果nth写入器实现为函数,则需要两次遍历10k个列表节点,但在setf扩展器中可以用单次遍历完成。


这正是我在寻找的答案!谢谢! - Michaël Le Barbier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接