通用宏? (作为通用函数的扩展)

时间:2017-04-06 18:26:34

标签: generics macros common-lisp destructuring

保罗·格雷厄姆在On Lisp,第18章,提出了许多有趣的宏来解构各种对象,扩展了destructuring-bind提供的基本树解构。例如,用于根据模板对结构对象的字段进行解构的宏如下(在with-slots CLOS宏之后进行模式化):

(defmacro with-structure ((name . fields) struct &body body)
  "Destructuring bind for the fields of a structure object."
  (let ((gs (gensym)))
    `(let ((,gs ,struct))
       (symbol-macrolet ,(mapcar #'(lambda (f)
                                     `(,f (,(mksymbol name f) ,gs)))
                           fields)
         ,@body))))

(defun mksymbol (&rest args)
  "Creates a symbol by concatenating the arguments."
  (values (intern (apply #'mkstring args))))

(defun mkstring (&rest args)
  "Concatenates arguments into a string."
  (with-output-to-string (stream)
    (dolist (arg args)
      (princ arg stream))))

现在:

(defstruct person name age)
PERSON
(defparameter p1 (make-person :name "Eli" :age 19))
P1
(with-structure (person- age) p1 (incf age))
20
p1
#S(PERSON :NAME "Eli" :AGE 20)

Graham还提供单独的宏模板,用于解构其他一些对象,如序列和数组。我的问题是关于添加另一层抽象是否合理,并使用类似(defmacro with-object (pattern (object type) &body body) ...)的定义将这些各种宏合并到一个调用中。这类似于编写泛型函数,其中每个要解构的对象将使用适当的类型/类扩展。但是,宏扩展阶段似乎可能需要包含一些增量编译以确定对象类型(除非它是由用户声明的)。编译可以与扩展交错,以实现这样的"泛型"操作;还是有更简单的方法?

0 个答案:

没有答案