【发布时间】:2018-09-25 22:58:44
【问题描述】:
我正在尝试创建一堆千篇一律的函数并将它们粘贴在哈希中。到目前为止,我已经有了一个可以扩展成这样一个函数的宏:
(defmacro make-canned-format-macro (template field-names)
`(function (lambda ,field-names
(apply #'format `(nil ,,template ,,@field-names)))))
(defparameter *cookie-cutter-functions* (make-hash-table))
(setf (gethash 'zoom-zoom *cookie-cutter-functions*)
(make-canned-format-macro "~A-powered ~A" (fuel device)))
(setf (gethash 'delicious *cookie-cutter-functions*)
(make-canned-format-macro "~A ice cream" (flavor)))
(setf (gethash 'movie-ad *cookie-cutter-functions*)
(make-canned-format-macro "~A: A ~A and ~A film" (title star co-star)))
那个重复的setf、gethash、make-canned-format-macro 模式太像样板了,所以我试着把它转换成一个循环:
(loop
for template in '(('zoom-zoom "~A-powered ~A" (fuel device))
('delicious "~A ice cream" (flavor))
('thematic "~A: A ~A and ~A film" (title star co-star)))
do (let ((func-name (car template))
(format-string (cadr template))
(params (caddr template)))
(setf (gethash func-name *cookie-cutter-functions*)
(make-canned-format-macro format-string params))))
不幸的是,这是因为 make-canned-format-macro 是在 值 PARAMS 而不是值 OF params 上运行的,因为它在编译时进行了宏扩展,不在运行时评估。但正如我在询问this question 时了解到的,make-canned-format-macro 不能作为函数工作,因为它需要在编译时构造lambda 表单。 (至少,我认为这是我从中学到的东西?请告诉我我在这一点上错了!我希望我的函数工厂是一个函数,而不是一个宏!)
我目前的想法是编写一个turn-this-list-of-templates-into-make-canned-format-macro-forms 宏而不是循环。这是正确的做法(或至少不是疯狂的做法),还是有更好的方法?
【问题讨论】:
标签: macros lisp common-lisp code-generation