我有一个程序,它将一大块数据和一系列规则作为输入,同时应用一组标准规则和作为数据块输入的规则。两个输入的大小可能会有所不同。
我希望能够写出这样的规则列表:
(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
)
现在,规则更加冗长 - 它们看起来更像是
(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
)
后一种形式对我来说看起来很丑陋,但我无法弄清楚如何编写一个可以处理可变长度&rest
参数的宏,迭代它并返回转换后的结构。使用defun
而不是defmacro
并不是真的在桌子上,因为(正如希望示例所示)我试图控制规则列表的评估,而不是在我的程序时评估列表首先看到它,一旦你需要控制评估,你就在defmacro
领域。在这种情况下,棘手的问题是rule-action-macro
部分 - 让解释器读取它并使用其扩展值是有问题的。
如何创建一个处理可变长度参数的宏,以便我能够以简洁的方式编写规则列表?
答案 0 :(得分:5)
defmacro
会愉快地接受&rest
参数
(对于Emacs Lisp,请参阅Defining Macros,对于Common Lisp,请参阅Macro Lambda Lists。)
然后你可以在宏体中做任何你想要的东西 - 例如,迭代它。请记住,宏不仅仅是反引号!
E.g:
(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))