Lisp风格:setq与setf

Lisp风格:setq与setf,lisp,common-lisp,Lisp,Common Lisp,彼得·诺维格(Peter Norvig)在上一篇文章中提到了特异性和一致性之间的权衡,以及选择使用setq或setf将变量更新为值的问题。你推荐什么?您是否遇到过这样一种情况,即它的重要性远远超过可读性?使用setq更低级,但setf的性能不是问题。setf允许您(或库编写器)提供自定义setf行为,如设置自定义数据结构的部分。我说:除非你有理由不这样做,否则你要到处跟着setf 另请参见实用通用Lisp,第3章:“SETF宏是通用Lisp的主要赋值运算符。”PCL在线免费提供:您可以在任何可以

彼得·诺维格(Peter Norvig)在上一篇文章中提到了特异性和一致性之间的权衡,以及选择使用setq或setf将变量更新为值的问题。你推荐什么?您是否遇到过这样一种情况,即它的重要性远远超过可读性?

使用setq更低级,但setf的性能不是问题。setf允许您(或库编写器)提供自定义setf行为,如设置自定义数据结构的部分。我说:除非你有理由不这样做,否则你要到处跟着setf


另请参见实用通用Lisp,第3章:“SETF宏是通用Lisp的主要赋值运算符。”PCL在线免费提供:

您可以在任何可以使用
setq
的地方使用
SETF
。实际上,
setf
实际上是一个基于
setq
的宏。因此,这应该是一个纯粹的可读性和风格问题


我看到的几乎所有代码都避免使用
setq
,而使用
setf

我建议您遵循诺维格在该部分的最后建议:保持一致。”“可读性”当然是在编程中做出任何选择的最重要原因。如果与读者(可能在2个月后)沟通您正在处理符号的整个值单元很重要,则使用
setq
;否则使用
setf
。但只有在保持一致的情况下,setf才是“set field”,它会改变一个位置,并且可以有用户扩展。
setq设置为引用第一个参数。

FWIW,我总是使用
setf
。如果我稍微更改代码的结构,我只需要更改“place”,而不是place和操作符(setq->setf)

另外,不要担心性能,setf与符号的setq完全相同:

CL-USER> (macroexpand '(setf foo 42))
(SETQ FOO 42)

如果您在任何地方都使用setf而不是setq,您就不会错


正是这样的事情阻碍了Common Lisp的发展,很多未使用的东西实现者仍然需要支持。

我反对第二句话。SETF是对几个赋值构造的方便抽象,其中一个是SETQ。如果没有SETQ.2Svante,就无法实现SETF。但是很难想象在什么情况下需要使用SETQ而不是SETF。这不是重点——没有人使用标记体并使用高级代码,但许多常见构造的实现都依赖于它们。