【问题标题】:Quote a reader macro invocation引用阅读器宏调用
【发布时间】:2012-11-02 02:03:16
【问题描述】:

有没有办法引用阅读器宏的调用?更具体地说,我想创建一个宏,一旦评估,它将生成一个 defclass 语句和一个相应的 XML 文件。这可能吗?

我考虑过使用#.( ... ) 阅读器宏,但我认为宏参数未绑定在阅读器宏中使用。这是正确的吗?

因此,我的第二个想法是尝试生成一个包含读取器宏的语句,但我不确定是否有办法做到这一点。

关于在扩展宏调用时生成 XML 文件有什么建议吗?

提前感谢您的任何想法。

【问题讨论】:

    标签: macros lisp common-lisp


    【解决方案1】:

    “阅读器宏”和“宏”是完全不同的野兽,用来做非常不同的事情。

    “阅读器宏”通常是一个函数。它们绑定到一个(或两个特定序列)字符,并改变读取源代码的方式。它们不是关于代码,而是关于对象创建。

    对于“阅读器宏”,没有明确定义“宏参数”是什么(可能除了首先导致调用阅读器宏的字符序列,这很有用例如,当您阅读列表时,将() 匹配)。

    【讨论】:

      【解决方案2】:

      类似的东西:

      (defmacro def-wsdl-class (name (&rest supers)
                                 (&rest slots)
                                 &rest options)
        `(progn
           (eval-when (:compile-toplevel :execute)
             (with-open-file (xml-file (make-pathname :name (string-capitalize name)
                                                      :type "wsdl"
                                                      :defaults (or *compile-pathname*
                                                                    *load-pathname*))
                                       :direction :output
                                       :if-exists ,(getf options :if-wsdl-exists :error))
               (when xml-file
                 (spit-xml xml-file ',name ',supers ',slots ,@options))))
          `(defclass ,name (,@supers)
             (,@slots)
             ,@(chew options)))))
      

      编辑:要回答您的原始问题,您通常不能(反)引用阅读器宏。它们在读取语法的地方执行,我们称之为读取时间。阅读器宏不参与正常的宏扩展,它们在宏扩展之前起作用。

      您可能会创建一个阅读器宏,它知道它在反引号阅读器宏中被调用以使用它,但它需要知道或更改反引号阅读器宏的实现相关行为。

      但是,您可以从阅读器宏返回反引号表单。

      【讨论】:

      • 谢谢!这正是我所需要的!但是有一个问题,通过将 :execute 传递给 eval-when,它是否还会在执行时重新生成 XML 文件?我花了一天时间研究 ASDF,我认为可以对 compile-op 进行子类化以生成 XML 文件,但是解析源代码以搜索“def-wsdl-class”并不是很容易,感觉有点笨拙。再次感谢您的回答!
      • @JanitoVaqueiroFerreiraFilho,就是这样。 :compile-toplevel 告诉编译器这个顶级表单也将在编译时执行。缺少:load-toplevel 告诉编译器它可以跳过它的处理(例如编译)和加载器它不能执行它。 :execute 告诉任何正在执行的代码这也应该被执行。因此,def-wsdl-class 可能会以文件的顶层形式或 REPL 的形式出现,并且将创建 XML 文件。加载后,它不会重新创建文件。
      • @JanitoVaqueiroFerreiraFilho,另一种选择可能是使用依赖于实现的compiler-let,例如(compiler-let ((*force-xml* (eval-when (:compile-toplevel :execute) :supersede))) (with-open-file ... :if-exists *force-xml*))。这样,文件可以随时生成,但在加载时它只会在文件不存在时生成。
      • @JanitoVaqueiroFerreiraFilho,最后请注意,我为 xml-file 跳过了至少 1 个 gensym。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多