为了在common-lisp中进行快速原型设计,能够在任意数据结构中轻松地功能修改对象将是方便的。这似乎涉及在数据结构中的某个位置调用一个任意函数,用函数调用的结果替换该位置的对象。 Common-lisp对特定类型的对象有许多专门的修改宏(例如incf
,push
,getf
等),而setf
用于广义位置修改(例如,setf-second
,setf-aref
,setf-gethash
等)。但是,不是为其他对象类型发明新的专用宏,或者必须在心理上考虑每个宏的特性(减慢开发速度),而是使用比{{1更易于使用的通用setf类修改功能可能更好。 }}。例如,代替setf
或(setf (second (getf plist indicator)) (1+ (second (getf plist indicator))))
,可以使用common-lisp或用户提供的任何普通的一个参数函数(或lambda-expression)来编写(incf (second (getf plist indicator)))
。这是对代码的尝试:
(callf (second (getf plist indicator)) #'1+)
这样的事情是否适用于所有一般情况,并且实际上是否可以简化代码?
答案 0 :(得分:2)
callf
(defmacro _f (op place &rest args)
"Modify place using `op`, e.g., (incf a) == (_f a 1+)"
(multiple-value-bind (vars forms var set access)
(get-setf-expansion place)
`(let* (,@(mapcar #'list vars forms)
(,(car var) (,op ,access ,@args)))
,set)))
这使用get-setf-expansion
- generalized reference处理的主力。
请注意,_f
仅适用于single-value个地方。
IOW,(_f (values a b c) 1+)
将不增加所有3个变量。
尽管如此,解决这个问题并不是那么难......
真的取决于您的编码风格和您正在解决的具体问题。