是否可以在 Common Lisp 中定义语法规则宏

Tsi*_*Hui 4 scheme common-lisp syntax-rules

我了解到在方案中定义一个小宏很容易syntax-rules。是否可以定义一个宏来返回一个可以在 Common Lisp 中syntax-rules读取的列表?defmacro

这可能会像这样工作:

(defmacro and (&rest rest)
  (syntax-rules (rest) ()
    ((_)         t)
    ((_ x)       x
    ((_ x y)     (if x (if y y nil) nil))
    ((_ x y ...) (if x (and y ...) nil))))
Run Code Online (Sandbox Code Playgroud)

ign*_*ens 6

Tim Bradshaw 的destructuring-match目的是使宏中的这种模式匹配变得容易:它是caseand的组合destructuring-bind,因此每个子句的键都具有解构 lambda 列表的语法。CL 还有其他几种模式匹配系统,但这个系统明确旨在编写宏:它不是通用的数据结构匹配工具,只是destructuring-bind.

它附带了一个名为 的小示例宏(本身是使用 编写的,destructuring-match并且扩展使用的东西destructuring-match!)define-matching-macro,您可以在其中编写 的版本and,此处称为et。我认为以下两个宏是正确的,但我没有考虑太多。

(define-matching-macro et
  "This is meant to be AND"
  ((_) 't)
  ((_ x) x)
  ((_ x . more ) `(if ,x (et ,@more) nil)))
Run Code Online (Sandbox Code Playgroud)

您也可以仅destructuring-match在普通defmacro宏中使用。在这里,我没有用来&whole获取整个表单,因此我们不必费心处理car表单的:

(defmacro et (&rest forms)
  "This is also meant to be AND"
  (destructuring-match forms
    (() 't)
    ((x) x)
    ((x . more) `(if ,x (et ,@more) nil))))
Run Code Online (Sandbox Code Playgroud)

笔记:

  • destructuring-match与Scheme一样使用名称为"_"空白的符号,因此您不需要声明它们被忽略,它们都是彼此不同的,事实上您可能不会在子句正文中引用它们;但它根本不做Scheme的x ...事情,所以你只需要使用点式lambda列表或&rest任何你喜欢的东西;
  • 这些不是卫生宏,它们只是模式匹配宏;
  • 这些比你的例子简单一些,但我认为它们已经足够了;
  • 你的宏实际上并不安全,因为(if x x nil), 以及冗余(它只是x) 可能会计算x两次,这是不安全的。