【问题标题】:How can I destructure an &rest argument of varying length in my elisp macro?如何在我的 elisp 宏中解构不同长度的 &rest 参数?
【发布时间】:2013-02-12 22:48:07
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: macros lisp elisp


    【解决方案1】:

    defmacro 很乐意接受 &rest 参数 (请参阅 Defining Macros 了解 Emacs Lisp 和 Macro Lambda Lists 了解 Common Lisp)。

    然后你可以在宏体中用它做几乎任何你想做的事情——例如,迭代它。请记住,宏不仅仅是反引号!

    例如:

    (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))
    

    【讨论】:

    • 好的,我认为您的回答让我走向“我之前所做的事情是错误的”。可能我不太了解如何让宏返回我想要的更改后的结构,因此得到的结果在我看来就像“它不起作用,&rest 只是我的一个肿块不能操纵。”我会在那里尝试你的建议。
    • 打破我对这种情况的心理模型的真正问题实际上有些不同:我将带引号的列表作为参数传递给宏。我相信你可以想象这让生活变得多么艰难。但是,我意识到这一点的方式是使用您的示例并根据我的目的慢慢修改它。既然你的回答让我到达了我需要去的地方,那就接受了。 :)
    • `(progn ,@forms)...啊,这正是我需要的。
    猜你喜欢
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多