2

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

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

(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参数、迭代它并返回转换后的结构的宏。使用 adefun而不是 adefmacro并不是真的在桌面上,因为(希望示例显示)我试图控制规则列表的评估,而不是在我的程序第一次看到它时评估列表,并且一旦你需要控制评估,你在defmacro领域。在这种情况下,棘手的问题是rule-action-macro部分 - 让解释器阅读并使用其扩展值是有问题的。

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

4

1 回答 1

5

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))
于 2013-02-12T23:32:57.197 回答