如何在我的elisp宏中构造一个不同长度的& rest参数?

时间:2013-02-12 22:48:08

标签: macros lisp elisp

我有一个程序,它将一大块数据和一系列规则作为输入,同时应用一组标准规则和作为数据块输入的规则。两个输入的大小可能会有所不同。

我希望能够写出这样的规则列表:

(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部分 - 让解释器读取它并使用其扩展值是有问题的。

如何创建一个处理可变长度参数的宏,以便我能够以简洁的方式编写规则列表?

1 个答案:

答案 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))