我有一个程序,它将一大块数据和一系列规则作为输入,同时应用一组标准规则和作为数据块输入的规则.两个输入的大小可能会有所不同.
我希望能够写出这样的规则列表:
(rule-generating-macro
(rule-1-name rule-1-target
(rule-action-macro (progn actions more-actions)))
(rule-2-name rule-2-target
(rule-action-macro (or (action-2) (default-action))))
;; more rules
)
Run Code Online (Sandbox Code Playgroud)
现在,规则更加冗长 - 它们看起来更像
(defvar rule-list
`((rule-1-name rule-1-target
,@(rule-action-macro (progn actions more-actions)))
(rule-2-name rule-2-target
,@(rule-action-macro (or (action-2) (default-action))))
;; more rules
)
Run Code Online (Sandbox Code Playgroud)
后一种形式对我来说看起来更加丑陋,但我无法弄清楚如何编写一个可以处理可变长度&rest参数的宏,迭代它并返回转换后的结构.使用a defun而不是a defmacro实际上不在桌子上,因为(正如希望示例所示)我试图控制规则列表的评估,而不是在我的程序第一次看到它时评估列表,并且一旦你需要控制评价,你在defmacro境内.在这种情况下,棘手的问题是rule-action-macro部分 - 让解释者阅读并使用其扩展值是有问题的.
如何创建一个处理可变长度参数的宏,以便我可以简洁地编写规则列表?
defmacro很乐意接受一个&rest参数(请参阅为Emacs Lisp 定义宏和Common Lisp的宏Lambda列表).
然后你可以在宏体中做任何你想要的东西 - 例如,迭代它.请记住,宏不只是反引号!
例如:
(defmacro multidefvar (&rest vars)
(let ((forms (mapcar (lambda (var) `(defvar ,var)) vars)))
`(progn ,@forms)))
(macroexpand '(multidefvar a b c d))
==> (PROGN (DEFVAR A) (DEFVAR B) (DEFVAR C) (DEFVAR D))
Run Code Online (Sandbox Code Playgroud)