【问题标题】:Simplifying complex setf expressions简化复杂的 setf 表达式
【发布时间】:2017-02-07 21:30:28
【问题描述】:

为了在 common-lisp 中进行快速原型设计,能够轻松地对任意数据结构中的对象进行函数修改会很方便。这似乎涉及在数据结构中的某个位置调用任意函数,用函数调用的结果替换该位置的对象。 Common-lisp 有许多专门的修改宏(例如,incfpushgetf 等)用于特定类型的对象,setf 用于通用位置修改(例如,setf-second、@987654327 @、setf-gethash 等)。但是,与其为其他对象类型发明新的专用宏,或者不必考虑每个宏的特性(减慢开发速度),不如拥有一个比setf 更易于使用的通用 setf 修改功能。 .例如,代替(setf (second (getf plist indicator)) (1+ (second (getf plist indicator))))(incf (second (getf plist indicator))),可以写(callf (second (getf plist indicator)) #'1+),使用由common-lisp 或用户提供的任何正常的单参数函数(或lambda 表达式)。这是代码的尝试:

(defun call (object function) (funcall function object))
(define-modify-macro callf (&rest args) call)

这样的事情是否适用于所有一般情况,它实际上可以在实践中简化代码吗?

【问题讨论】:

标签: reference macros common-lisp


【解决方案1】:

callf

我认为您正在寻找的是来自OnLisp 12.4 的_f

(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 个变量。 不过,解决这个问题并不难......

它实际上可以在实践中简化代码吗?

真的取决于您的编码风格和您要解决的具体问题。

【讨论】:

  • 就是这样。 OnLisp 中的讨论也很棒。
猜你喜欢
  • 2016-01-09
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 2014-03-10
相关资源
最近更新 更多